Connecting AI assistants (MCP)
Agrafe is a remote Model Context Protocol server. An MCP client such as Claude can read your deployed ontologies, run SPARQL queries against them and read your project glossaries, with your own permissions.
What it exposes
| Resources | One per deployment you can access: schema://ontology/{deployment_id}, the ontology as Turtle. Titled <project> v<version>; the description lists the concepts (up to 20 by name), the property count and the triple counts. |
Tool list_deployments | No arguments. Lists the deployments you can query: deployment and project ids, project name, your role (owner, editor or viewer), version, creation date and triple counts. |
Tool run_sparql_query | Arguments deployment_id and query. Runs a read-only SPARQL SELECT or ASK query against one deployment. |
Tool describe_concept | Arguments deployment_id and name. Returns one concept from the compiled schema as JSON: its IRI, parent and child concepts, and each property with its range and whether it is required. Not available for Turtle-origin projects. |
Tool get_glossary | Argument project_id (from list_deployments). Returns the project’s glossary, compiled from its current Dolfin sources: concepts, properties and rules, plus lint diagnostics. If the sources have errors, the tool answers with the diagnostics and whatever partial glossary could be built. |
| Prompts | explore_ontology (deployment_id), write_sparql_query (deployment_id, question) and explain_concept (deployment_id, concept). Ready-made instructions that walk the assistant through the resources and tools above. Each one ends with the PREFIX declarations of the deployment’s namespaces. All arguments are required. |
You can access your own projects and projects shared with you (accepted invitations), with their deployments. A deployment or project that does not exist and one you cannot access give the same error.
run_sparql_query returns at most 1000 rows. When more rows match, a second message says the result was truncated; page with LIMIT and OFFSET. A query still running after 10 seconds is cancelled.
Scopes
| Scope | Allows |
|---|---|
mcp:read | Connect, list and read resources and prompts, run list_deployments and describe_concept. |
mcp:query | Run run_sparql_query. |
glossary:read | Run get_glossary. |
A client that asks for no scope gets every scope it is allowed. A tool called without its scope answers access denied: missing <scope> scope. Connectors registered before glossary:read was offered to MCP clients must be reconnected to get it.
Connecting
Claude (claude.ai)
Add a custom connector with the URL https://agrafe.dolfin.fr/mcp. Claude registers itself as a public OAuth client (no secret, PKCE), sends you to Agrafe to log in and authorize, and connects. No configuration file is needed.
Claude Desktop and other stdio clients
Settings → MCP in Agrafe shows a ready-to-copy configuration that bridges through mcp-remote:
{
"mcpServers": {
"agrafe": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://agrafe.dolfin.fr/mcp/sse"]
}
}
}
Use Copy config and paste it into claude_desktop_config.json.
Endpoints
For integrators. Both transports are supported:
| Endpoint | |
|---|---|
POST, GET, DELETE /mcp | Streamable HTTP (protocol 2025-06-18 or 2025-03-26). |
GET /mcp/sse and POST /mcp/message?session_id=… | SSE transport (protocol 2024-11-05, older clients). |
initialize answers with the protocol version the client asked for when it is one of 2025-06-18, 2025-03-26 or 2024-11-05. Otherwise it answers with the newest, 2025-06-18, or with 2024-11-05 if the client sent no version.
On the streamable transport, POST /mcp takes one JSON-RPC request and returns one JSON response; batches are not supported. The response to initialize carries an Mcp-Session-Id header. Send it on every later request:
| Case | Status |
|---|---|
| Header missing | 400 |
| Unknown or expired session | 404 (start again with initialize) |
| Session opened by another user | 403 |
MCP-Protocol-Version header present but not a supported version | 400 |
GET /mcp with the session header opens a Server-Sent Events stream for messages from the server. Opening a new one replaces the previous stream. DELETE /mcp ends the session. A session with no open stream expires one hour after its last request.
Supported methods: initialize, ping, resources/list, resources/read, tools/list, tools/call, prompts/list, prompts/get. Any notifications/* message is acknowledged and ignored.
The server advertises resources.listChanged. When a project gets a new deployment, every open stream of every user who can access that project (owner or accepted share) receives notifications/resources/list_changed: the GET /mcp stream on the streamable transport, the /mcp/sse stream on the SSE transport. A streamable session with no GET /mcp stream open gets no notification. resources/subscribe is not supported: a deployment never changes once created.
Authorization is OAuth 2.1 with PKCE (S256):
| Endpoint | |
|---|---|
/.well-known/oauth-authorization-server | Server metadata. Lists client_secret_post and none as token authentication methods. |
/.well-known/oauth-protected-resource (also under a path suffix such as /mcp/sse) | RFC 9728 metadata. |
/oauth2/register | Dynamic client registration. token_endpoint_auth_method: "none" registers a public client with no secret. |
/oauth2/authorize, /oauth2/token, /oauth2/revoke, /oauth2/userinfo | The usual flow. |
Rate limits
POST /mcp, DELETE /mcp and POST /mcp/message are rate-limited per access token: 100 requests per minute by default (RATE_LIMIT_RPM on the server), counted separately from the data API. Over the limit, a request gets 429 Too Many Requests; wait and retry. Opening a stream (GET /mcp or GET /mcp/sse) is not limited. There is no per-plan query quota.
An unauthenticated request gets 401 with WWW-Authenticate: Bearer resource_metadata="…/.well-known/oauth-protected-resource", which is how a client discovers where to log in.
Behind a proxy
The SSE stream needs unbuffered responses. Agrafe sends X-Accel-Buffering: no, so nginx does not stall the handshake; other proxies must not buffer /mcp/sse either. HOST=https://… splash-graph/check-mcp.sh checks discovery, OAuth registration, both transports and the buffering.