Single-file HTTP MCP Server for Petfinder's API to find adoptable pets and the organizations that care for them, powered by Bun.
- OAuth token management – automatically handles Petfinder API authentication and token refresh
- Pet search capabilities – find adoptable pets by characteristics, location, and status
- Organization search – discover animal welfare organizations by name, ID, and location
- Single file implementation – complete MCP server in
simple-mcp-server.ts
- All capabilities are exposed as MCP tools over a Bun HTTP server
💡 Don't have Bun? Install it from https://bun.com/
This single-file MCP server uses:
- Bun's built-in HTTP server - Ultra-fast native HTTP handling with zero dependencies
- Zod - TypeScript-first schema validation for bulletproof input validation
- Petfinder API v2 - RESTful API for accessing adoptable pets and animal welfare organizations
- Native fetch - Built-in HTTP client for API calls
This MCP server handles Petfinder OAuth authentication automatically via query parameters:
Add your Petfinder credentials as query parameters to the MCP server URL:
http://localhost:3000/mcp?client-id=your-petfinder-client-id&client-secret=your-petfinder-client-secret
- Client credentials flow: Exchanges your credentials for access tokens automatically
- Multi-client token caching: Each client ID gets its own isolated token cache
- Automatic token management: Caches tokens in-memory with expiration tracking per client
- Token refresh: Automatically requests new access tokens when expired (every 3600 seconds)
- Bearer token authentication: Uses access tokens in
Authorization: Bearer {token}
headers
When adding this MCP server to MCP clients (Claude.ai, MCP Inspector, etc.):
- Use the server URL with your credentials:
http://localhost:3000/mcp?client-id=your-client-id&client-secret=your-client-secret
- No additional headers or configuration needed
- The server automatically extracts credentials from the URL query parameters
- Works seamlessly with all MCP clients that support HTTP servers
Capability | Petfinder API endpoint |
---|---|
Search for adoptable pets | GET /v2/animals with various search parameters |
Get specific pet details | GET /v2/animals/{id} for detailed pet information |
Search animal welfare organizations | GET /v2/organizations by name, location, or ID |
Get organization details | GET /v2/organizations/{id} for detailed organization info |
List all animal types | GET /v2/types for available animal types |
Get animal type details | GET /v2/types/{type} for specific animal type info |
List breeds for animal type | GET /v2/types/{type}/breeds for breeds of specific type |
Typical MCP request:
POST /mcp
{
"tool": "pets.search",
"input": {
"type": "dog",
"breed": "labrador",
"size": "medium",
"location": "90210",
"distance": 25,
"limit": 20
}
}
.
├─ simple-mcp-server.ts # Complete single-file MCP server
├─ package.json # Dependencies (bun, zod)
├─ tsconfig.json # TypeScript configuration
├─ Dockerfile # Container deployment
└─ README.md # This file
The entire MCP server is implemented in a single TypeScript file (simple-mcp-server.ts
) that handles OAuth token management and Petfinder API integration.
-
Petfinder API credentials
- Sign up for a developer account at https://www.petfinder.com/developers/
- Create an application to get your API Key (Client ID) and Secret
- No additional permissions or approval needed - the API uses OAuth client credentials flow
-
Bun ≥ 1.2.19 installed locally (or let Docker handle it).
Name | Example | Required | Description |
---|---|---|---|
PORT |
3000 |
❌ | Server port (defaults to 3000) |
🔑 Authentication: Credentials are provided via query parameters only - no environment variables needed!
Getting your credentials:
- Create a Petfinder account at petfinder.com if you don't have one
- Get your API Key (Client ID) and Secret at petfinder.com/user/developer-settings
- Use these credentials as query parameters when connecting to the MCP server
You can use the official MCP Inspector to interactively test this server.
-
Start the server in one terminal:
bun run simple-mcp-server.ts
-
Run the inspector in another terminal with your credentials:
npx @modelcontextprotocol/inspector "http://localhost:3000/mcp?client-id=your-client-id&client-secret=your-client-secret"
This will launch a web UI where you can see all available tools and manually trigger them with different parameters, making it easy to debug your tool logic.
# Install deps
bun install
# Run server on port 3000 (no environment variables needed!)
bun run simple-mcp-server.ts
Send a request:
curl -X POST "http://localhost:3000/mcp?client-id=your-client-id&client-secret=your-client-secret" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "pets.search",
"arguments": {
"type": "dog",
"breed": "labrador",
"location": "90210",
"distance": 25,
"limit": 10
}
}
}'
You’ll get real JSON responses from the Petfinder API using your provided credentials.
Route | Method | Purpose |
---|---|---|
/healthz |
GET/HEAD | Simple health-check (returns 200 OK ) |
All responses include Access-Control-Allow-Origin: *
so the MCP can be called from a browser without extra CORS configuration.
The server handles Petfinder API authentication automatically:
- Token exchange: Uses
CLIENT_ID
andCLIENT_SECRET
to request access tokens fromhttps://api.petfinder.com/v2/oauth2/token
- In-memory caching: Caches access tokens in-memory with expiration tracking (tokens expire after 3600 seconds)
- Automatic refresh: Detects expired tokens and automatically requests new ones before making API calls
- Bearer authentication: Includes
Authorization: Bearer {access_token}
header in all Petfinder API requests
The OAuth flow follows Petfinder's client credentials pattern:
curl -d "grant_type=client_credentials&client_id={CLIENT-ID}&client_secret={CLIENT-SECRET}" \
https://api.petfinder.com/v2/oauth2/token
Response format:
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "..."
}
Tool | Purpose | Input → Output |
---|---|---|
pets.search |
find adoptable pets | { type?, breed?, size?, location?, distance?, limit? } → pets array |
pets.get |
get specific pet details | { id } → detailed pet object |
organizations.search |
find animal welfare orgs | { name?, location?, state?, country?, limit? } → organizations array |
organizations.get |
get specific org details | { id } → detailed organization object |
types.list |
list all animal types | {} → animal types array |
types.get |
get animal type details | { type } → detailed animal type object |
breeds.list |
list breeds for animal type | { type } → breeds array |
🔍 Search Parameters:
- Pet search: Filter by animal type (dog, cat, etc.), breed, size (small/medium/large), location (ZIP/postal code), distance radius
- Organization search: Filter by name, location, state/province, country
- Pagination: Use
limit
parameter to control result count (default: 20, max: 100) - Location-based: Distance searches require a location parameter (ZIP code, city, etc.)
📊 Response Data:
- Pet objects: Include photos, description, age, gender, size, breed, contact info, and adoption status
- Organization objects: Include name, address, phone, email, website, and mission statement
- Rich metadata: Comprehensive information to help users make informed adoption decisions
This server includes comprehensive request logging to help you integrate with MCP clients:
Example with query parameter authentication:
curl -X POST "http://localhost:3000/mcp?client-id=your-client-id&client-secret=your-client-secret" \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}'
Debug Output: The server logs all incoming requests, query parameters, and authentication attempts to help you see exactly what your MCP client is sending and troubleshoot any authentication issues.
Pet Search Examples:
# Find dogs in Los Angeles area
{ "type": "dog", "location": "90210", "distance": 25 }
# Find small cats ready for adoption
{ "type": "cat", "size": "small", "limit": 10 }
# Find specific breed
{ "type": "dog", "breed": "golden retriever", "location": "New York, NY" }
Organization Search Examples:
# Find shelters by name
{ "name": "SPCA" }
# Find organizations in specific state
{ "state": "CA", "limit": 15 }
# Find organizations near location
{ "location": "Austin, TX" }
Typical Pet Response includes:
id
- Unique pet identifiername
- Pet's namephotos
- Array of photo URLsdescription
- Detailed descriptionbreeds
- Primary and secondary breedsage
,gender
,size
- Basic characteristicscontact
- Organization contact informationstatus
- Adoption status (adoptable, pending, etc.)