Getting started¶
Connect an MCP client and call your first tool.
One click, any client¶
The button reads the demo's server card — the document every fastgeoapi deployment with MCP enabled publishes about itself (SEP-2127) — and opens a chooser with the install path for your client: a deep link, a command line, a configuration snippet, or the walkthrough of your app's connector settings. Twenty-six clients, one document.
Sign in with GitHub. On first use your client sends you to the demo's login, which accepts GitHub accounts: anyone with one can install the connector and call the tools. Running your own fastgeoapi? Your deployment publishes its own card — see Let your users install it with one click.
The sections below do by hand what the button does for you.
Connect Claude Desktop (native connector)¶
Claude Desktop supports remote MCP servers natively as custom connectors — no local shim or config-file edit required. This is the recommended path:
- Open Settings → Connectors → Add custom connector
- Paste the server URL:
https://your-domain.com/mcp/(the trailing slash is optional — both variants are served) - On first use, complete the OAuth login in the browser popup; the connector then refreshes tokens silently
Avoid running mcp-remote alongside the connector
If an older mcp-remote-based entry for the same server is still present in claude_desktop_config.json, remove it: the two clients race through the OAuth flow and the mcp-remote process can wedge on its fixed callback port (43711), leaving the tools list stuck.
Claude identifies itself with CIMD, not Dynamic Client Registration
Claude presents a URL as its client_id (https://claude.ai/oauth/mcp-oauth-client-metadata) and publishes its own metadata there, rather than registering through DCR. Two practical consequences: the authorization server must have CIMD enabled (it is, by default), and the connector never holds a client secret — the flow is protected by PKCE.
Worth knowing when debugging: a failure on the CIMD path is invisible to a DCR-based test. If the connector cannot authorize while a manually registered client can, replay Claude's exact request — the `client_id` URL is in the server access log — instead of assuming the two paths behave alike.
Connect stdio-only clients (mcp-remote)¶
For MCP clients that only speak stdio, front the server with mcp-remote in the client configuration file (for Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows):
{
"mcpServers": {
"fastgeoapi": {
"command": "npx",
"args": ["mcp-remote", "https://your-domain.com/mcp/"]
}
}
}
For local development over plain HTTP, add the --allow-http flag:
{
"mcpServers": {
"fastgeoapi": {
"command": "npx",
"args": ["mcp-remote", "http://localhost:5000/mcp/", "--allow-http"]
}
}
}
mcp-remote caveats
mcp-remote keeps tokens only in process memory (every restart re-runs the full OAuth dance) and binds a fixed OAuth callback port. If the client loops on authentication, check for zombie processes with lsof -i :43711 and kill them.
Connect via Streamable HTTP¶
The server speaks MCP over the Streamable HTTP transport (the legacy /mcp/sse endpoint no longer exists) and negotiates the protocol version per connection, so both the sessionless 2026-07-28 revision and the earlier handshake work. Clients with native remote MCP support connect directly to:
Or with HTTPS in production:
Test the MCP Server¶
You can test the MCP server endpoints directly:
# Check the MCP endpoint is alive (Streamable HTTP): expect 401 with OAuth
# enabled, 406 without the proper Accept headers — both mean it is up
curl -i http://localhost:5000/mcp/
# Get OAuth metadata (when OAuth is enabled)
curl http://localhost:5000/.well-known/oauth-protected-resource/mcp/
# Get authorization server metadata (RFC 8414 path-aware)
curl http://localhost:5000/.well-known/oauth-authorization-server/mcp
Available MCP Tools¶
The MCP server automatically generates tools from the pygeoapi OpenAPI specification. The available tools depend on your pygeoapi configuration and enabled OGC API standards.
Core OGC API Tools¶
Tool names come from the OpenAPI operationIds, so collection-specific tools embed the collection name (the demo configuration with the lakes and obs collections yields 27 tools). For example:
| Tool | Description | OGC API |
|---|---|---|
getLandingPage | Get the API landing page with links to all resources | Common |
getConformanceDeclaration | Get OGC API conformance classes | Common |
getCollections | List all available feature collections | Features |
describeLakesCollection | Get metadata for the lakes collection | Features |
getLakesFeatures | Query features from lakes with filters | Features |
getLakesFeature | Get a specific lakes feature by ID | Features |
getLakesQueryables | Get queryable properties of the lakes collection | Features |
getLakesSchema | Get the JSON Schema of the lakes collection | Features |
OGC API - Processes Tools¶
If OGC API - Processes is enabled in your pygeoapi configuration (names below are for the demo hello-world process; note that fastmcp sanitizes - to _):
| Tool | Description |
|---|---|
getProcesses | List all available processes |
describeHello_worldProcess | Get details about the process |
executeHello_worldJob | Execute the process with input parameters |
getJobs / getJob | List jobs / get the status of a job |
getJobResults | Get the results of a completed job |
OGC API - Tiles Tools¶
If a collection serves tiles (names below are for the demo lazio-roads-tiles collection):
| Tool | Description |
|---|---|
getLazio_roads_tilesTileSets | List the tilesets of the collection |
getLazio_roads_tilesTileSet | Describe one tileset, given its tile matrix set |
The tiles themselves are not tools, since a model cannot use a binary tile. pygeoapi takes the operationIds of these two operations from OGC API - Tiles and puts the collection in front: describeLazio-roads-tiles.collection.vector.getTileSetsList has 59 characters, and FastMCP cuts tool names at 56. fastgeoapi names them after get<Collection>Features and get<Collection>Feature instead.
Example Tool Usage¶
When using Claude Desktop with the MCP server, you can ask questions like:
- "What feature collections are available?"
- "Show me the first 10 features from the 'lakes' collection"
- "What are the queryable properties for the 'buildings' collection?"
- "Get the feature with ID 'building-123' from the buildings collection"
Claude will automatically use the appropriate MCP tools to fulfill these requests.
OAuth Discovery Endpoints¶
When OAuth is enabled, the following RFC-compliant endpoints are available:
| Endpoint | RFC | Description |
|---|---|---|
/.well-known/oauth-protected-resource/mcp/ | RFC 9728 | Protected resource metadata |
/.well-known/oauth-authorization-server/mcp | RFC 8414 | Authorization server metadata (path-aware) |
/.well-known/openid-configuration | OIDC 1.0 | OIDC discovery alias (fastmcp >= 3.4) |
/mcp/register | RFC 7591 | Dynamic client registration |
/mcp/authorize | OAuth 2.0 | Authorization endpoint |
/mcp/token | OAuth 2.0 | Token endpoint |
Troubleshooting¶
MCP Server Not Starting¶
If the MCP server doesn't start, check:
FASTGEOAPI_WITH_MCP=trueis set in your.envfile- The
pygeoapi-openapi.ymlfile exists and is valid - Check the logs for any OpenAPI parsing errors
# Check if OpenAPI file exists
ls -la pygeoapi-openapi.yml
# Start with debug logging
DEV_LOG_LEVEL=debug fastgeoapi run
OAuth Authentication Failing¶
If OAuth authentication fails:
- Verify your OIDC well-known endpoint is accessible:
-
Check that client ID and secret are correct
-
Ensure the redirect URI is configured in your IdP:
- For local development:
http://localhost:5000/mcp/auth/callback - For production:
https://your-domain.com/mcp/auth/callback
mcp-remote Connection Issues¶
If mcp-remote can't connect:
- Ensure the MCP server is running and accessible
- Check that the URL ends with a trailing slash:
http://localhost:5000/mcp/ - For HTTP (non-HTTPS), use the
--allow-httpflag - Check for CORS issues in browser-based clients
Client Shows "Connected" but the Tool List Is Empty¶
Different symptom, different cause: the connector is green and there is nothing to call — the tools simply aren't listed.
"Connected" reflects the OAuth grant the client has stored, not a live capability check. If that access token is no longer accepted — it outlived its TTL and the refresh failed, or it was minted by a previous server build — the client's tools/list is answered 401 and it keeps an empty tool registry rather than re-running authorization. Nothing recovers on its own.
Server-side the signature is unmistakable: repeated
from the client's address, with no POST /mcp/token in between — the client is retrying with the dead token instead of refreshing it.
The immediate fix is to disable and re-enable the connector, which re-runs the authorization dance.
If it comes back on a regular cadence, the cause is the token lifetime, and the first thing to check is not FASTGEOAPI_MCP_ACCESS_TOKEN_EXPIRY_SECONDS but whether the IdP is issuing a refresh token at all: without one that setting is silently capped at the upstream lifetime, so a server configured for days behaves as if configured for an hour. Configuration covers how to tell the two apart and what each IdP needs.
Client Shows "Connected" but Tool Calls Fail¶
If the client UI reports the server as connected but tool invocations error out (Claude Desktop: "couldn't send tool approval"), the client is usually holding a stale connection or session from before a server suspend/redeploy:
- Start a new conversation (MCP sessions are per-conversation in Claude Desktop)
- If that's not enough, disable and re-enable the connector (or restart the client)
Server-side this class of problem is mitigated by the stateless transport: requests never depend on prior server state, so once the client opens a fresh connection everything works without re-authentication.
Exploring with third-party clients¶
Two failure modes look identical from a generic MCP CLI — an opaque "server returned an error" — but have different causes.
The server requires authentication. With OAuth enabled every MCP request without a token is answered 401 plus the RFC 6750 challenge. Tools that cannot authenticate simply cannot list tools. Use a client that performs the OAuth flow — the reference one has a dedicated page: Verifying with the MCP Inspector.
Protocol versions are not a problem anymore. The server negotiates the sessionless 2026-07-28 protocol as well as the legacy initialize handshake (see Protocol versions), so clients on either side of that change connect without configuration. If a client still fails after authenticating, the protocol is the wrong suspect.
Enable Debug Logging¶
Enable debug logging to see detailed MCP server activity:
This will show:
- OAuth flow steps
- Tool invocations
- API calls to pygeoapi
- Token validation results