Knowledge Graph MCP Server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Knowledge Graph MCP Serversearch for accounts in the software industry"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Knowledge Graph MCP Server
Model Context Protocol (MCP) server that exposes a fictional CRM knowledge graph — enterprise Accounts and customer Contacts — for querying from Claude, ChatGPT, Adobe Coworker, or any other MCP-compatible client.
The graph is a plain Turtle/RDF file (data/knowledge_graph.ttl), loaded
into memory with rdflib and queried via
SPARQL. All data is synthetic/made-up — it does not represent any real
company or person.
This server mirrors the deployment setup used by the sibling
intervals-mcp-serverproject (Docker + Render + optional OAuth), swapping a REST API integration for a self-contained knowledge graph.
What's in the graph?
8 fictional enterprise accounts across industries (manufacturing, financial services, software, retail, healthcare, logistics, energy, education), each with tier, region, ARR, employee count, health score, renewal date, and account owner.
19 fictional contacts linked to those accounts, each with a job title, sales role (Economic Buyer / Champion / Influencer / User), email, phone, champion flag, sentiment, and last-contacted date.
See src/kg_mcp_server/tools/schema.py (get_graph_schema tool) for the
full property list and namespace.
Related MCP server: pipedrive-pj
Setup — Deploy to Render (recommended)
The fastest way to get started is to deploy the server to Render as a Docker Web Service. No local installation required.
1. Create a Web Service on Render
Push this folder to its own GitHub repository.
Go to render.com → New → Web Service (or use the included
render.yamlwith New → Blueprint).Connect your GitHub repository.
Configure the service:
Name:
kg-mcp-server(or your preferred name)Runtime: Docker
Instance Type: Free tier works fine
💤 Free tier cold starts: Render free-tier services sleep after 15 minutes of inactivity. The first request after sleeping may take 30-60 seconds while the container restarts and the graph reloads. Subsequent requests are fast.
2. Set Environment Variables
In the Render dashboard under Environment, add:
Key | Value | Description |
|
| Enables the remote transport (streamable HTTP) |
|
| Bind to all interfaces (required inside Docker) |
Optional — enable OAuth 2.0 to protect the endpoint:
Key | Value | Description |
|
| OAuth client ID; must match the connector config exactly |
|
| OAuth client secret / access token; must match the connector |
|
| Public HTTPS URL (no |
3. Deploy and Verify
Click Create Web Service — Render will build the Docker image and deploy
Wait for the build to complete (green status)
Note your service URL:
https://your-service-name.onrender.comTest by opening
https://your-service-name.onrender.com/mcpin a browser — you should get a response from the server
⚠️ Security Warning: Without OAuth, your Render endpoint is publicly accessible — anyone who discovers the URL can query the knowledge graph (read-only; there is no write/mutate capability). Either enable OAuth or do not share your service URL publicly.
Connecting Claude
Open Claude → Settings → Integrations (or MCP Servers)
Click Add
Fill in:
Name:
Knowledge GraphURL:
https://your-service-name.onrender.com/mcp(must end with/mcp)If OAuth is enabled, also set OAuth Client ID / OAuth Client Secret
Open a new conversation and ask "What MCP tools do you have available?" to confirm the connection.
Connecting ChatGPT / Adobe Coworker / other MCP clients
Any MCP-compatible client that supports remote (Streamable HTTP) servers can connect the same way:
MCP Server URL:
https://your-service-name.onrender.com/mcpOAuth Client ID / Secret if enabled
Available Tools
get_graph_schema— describe the graph's classes, properties, and namespaceget_graph_stats— triple/entity counts for the loaded graphlist_accounts— list/filter accounts by industry, tier, region, health scoresearch_accounts— free-text search across accountsget_account— full detail for one account, including its contactslist_contacts_for_account— list contacts working at a given accountsearch_contacts— free-text search across contactsget_contact— full detail for one contactrun_sparql_query— arbitrary read-only SPARQLSELECT/ASKquery
There is also an MCP resource, kg://guide, with a usage guide LLM clients
can load at the start of a conversation.
Troubleshooting Render Deployment
Service won't start — Check Render logs for build errors.
Claude/ChatGPT can't connect — Verify the URL ends with
/mcpand is publicly accessible. Try opening it in a browser."Authorization failed" with OAuth —
MCP_CLIENT_ID/MCP_CLIENT_SECRETmust match the connector exactly (case-sensitive),MCP_SERVER_URLmust be the public HTTPS URL without/mcp, and the connector URL must end with/mcp.Free tier cold starts — first request after sleeping may take 30-60 seconds.
Requirements
Python 3.12 or higher
uv (recommended package manager)
1. Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh2. Clone and install
cd kg_mcp_server
uv venv --python 3.12
source .venv/bin/activate # Windows: .venv\Scripts\activate
uv sync --all-extrasConfigure Claude Desktop (stdio)
mcp install src/kg_mcp_server/server.py --name "Knowledge Graph"Or manually add to claude_desktop_config.json:
{
"mcpServers": {
"Knowledge Graph": {
"command": "uv",
"args": [
"run", "--with", "mcp[cli]",
"--with-editable", "/path/to/kg_mcp_server",
"mcp", "run", "/path/to/kg_mcp_server/src/kg_mcp_server/server.py"
]
}
}
}Running over HTTP locally (for ChatGPT / remote testing)
export FASTMCP_HOST=127.0.0.1 FASTMCP_PORT=8000 MCP_TRANSPORT=http
python src/kg_mcp_server/server.pyForward the port with a tunnel (e.g. ngrok http 8000) to give a remote
client a public URL.
Editing the knowledge graph
Edit data/knowledge_graph.ttl directly — it's plain Turtle. Restart the
server (or call kg_mcp_server.graph.store.reload_graph()) to pick up
changes. Use KG_GRAPH_PATH to point at a different file entirely.
Development and testing
uv sync --all-extras
ruff check .
mypy src tests
pytest -v testsLicense
The GNU General Public License v3.0
Available Tools
9 toolsget_accountARead-only
Get full details for a single account, including its contacts.
Args: account: The account identifier (e.g. "acct-atlasforge"), or a name/substring to look up (e.g. "AtlasForge" or "atlasforge manufacturing"). include_contacts: Whether to also list contacts linked to this account (optional, defaults to True).
| Name | Required | Description | Default |
|---|---|---|---|
| account | Yes | ||
| include_contacts | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. The description adds useful behavioral context beyond that: the account argument accepts a substring/name lookup, and contacts are included by default via include_contacts=True. It does not address ambiguity handling or error behavior on lookup misses.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The first sentence front-loads the core purpose, and the Args block adds necessary parameter detail without filler. Every sentence earns its place, especially given the empty schema descriptions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value explanation is unnecessary, and both parameters are well covered. The main remaining gap is guidance on what happens if the name/substring lookup is ambiguous or matches multiple accounts, which matters for this lookup mode.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry parameter meaning, and it does: it explains the account identifier format with concrete examples and clarifies that include_contacts is optional and defaults to True. Both parameters are fully documented beyond the bare schema types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (get) and resource (single account) plus scope (full details including contacts). The word 'single' implicitly distinguishes it from list_accounts and search_accounts, but no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by 'single account' and the identifier/substring lookup, which suggests detail retrieval rather than browsing. However, there is no explicit when-to-use guidance or mention of alternatives like search_accounts or list_accounts.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_contactARead-only
Get full details for a single contact.
Args: contact: The contact identifier (e.g. "contact-adriana-koll"), or a name/substring to look up (e.g. "Adriana Koll" or "koll").
| Name | Required | Description | Default |
|---|---|---|---|
| contact | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds real behavioral value by disclosing that the identifier accepts a fuzzy name/substring resolution ("koll") rather than only an exact id, but it omits the ambiguity/failure behavior that this fuzzy matching implies.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded one-line purpose followed by a compact Args block; no wasted sentences. The Python docstring "Args:" formatting is slightly heavier than necessary for one parameter but costs little.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the lone parameter is fully documented with examples. The remaining gap is behavior on ambiguous or unmatched lookups, which matters for a substring-capable identifier but is not addressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the single required parameter is opaque ("Contact"), so the description must carry the load. It does so well, giving both the canonical id form ("contact-adriana-koll") and accepted name/substring forms with concrete examples.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ("Get full details for a single contact"), which inherently separates it from list_contacts_for_account and search_contacts siblings. It stops short of naming the sibling it displaces, so an agent must infer that bulk/partial matching belongs elsewhere.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by "single contact" versus the plural/multi-contact siblings, but there is no explicit statement of when to prefer this over search_contacts or get_account, and no guidance on what to do if the name/substring matches multiple contacts.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_graph_schemaARead-only
Describe the knowledge graph's classes, properties, and namespace.
Call this before writing a raw SPARQL query with run_sparql_query, or to understand what fields are available on accounts and contacts.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is fully covered without the description. The description adds the sequencing advice (call before run_sparql_query), which is more usage than behavior, and says nothing about caching, cost, or stability of the returned schema. Adequate but not rich beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core purpose and followed by the trigger condition. No filler, no repetition of the tool name or title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters and an output schema present, the description needs only to say what is returned conceptually and when to call it, which it does. It could still note the graph's scope or whether multiple schemas exist, but nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline of 4 applies. No parameter meaning is lost because no parameters exist.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (describe) and resource (the knowledge graph's classes, properties, namespace), so the agent knows exactly what comes back. It also implicitly separates itself from data-returning siblings like get_account or search_contacts, which return instances rather than the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the sibling tool run_sparql_query and the condition that should trigger this call first. It also volunteers a second use case (understanding account/contact fields), which covers the main reasons an agent would reach for this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_graph_statsARead-only
Return basic statistics about the loaded knowledge graph (triple/entity counts).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered structurally. The description adds that the output is a lightweight 'basic' summary limited to triple/entity counts, which usefully sets expectations, but says nothing about cost, latency, or the precondition of a loaded graph beyond the single adjective.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence that front-loads the verb and resource and appends the qualifying metric detail in parentheses. No filler, no restatement of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and a zero-parameter read-only tool has a small surface area to cover. The description is essentially sufficient; only the missing routing versus get_graph_schema keeps it from a 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the schema has nothing to document and there is no parameter semantics to clarify. Baseline 4 applies; the description correctly does not waste space describing nonexistent inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Return) and resource (statistics about the loaded knowledge graph) and goes further by naming the exact metrics (triple/entity counts). It does not explicitly distinguish itself from the nearby get_graph_schema sibling, so it falls just short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: 'loaded knowledge graph' hints the graph must already be loaded, and the metric list suggests a summary/overview use case. There is no explicit when-to-use, no exclusion, and no mention of the get_graph_schema alternative that an agent might confuse this with.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_accountsARead-only
List enterprise accounts in the knowledge graph, optionally filtered.
Args: industry: Case-insensitive substring match on industry (optional). tier: Exact match on account tier, e.g. "Strategic", "Enterprise", "Mid-Market" (optional). region: Exact match on region code, e.g. "NA", "EMEA", "APAC" (optional). min_health_score: Only return accounts with healthScore >= this value (optional, defaults to 0 i.e. no filtering).
| Name | Required | Description | Default |
|---|---|---|---|
| tier | No | ||
| region | No | ||
| industry | No | ||
| min_health_score | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds the useful behavioral detail that min_health_score defaults to 0, meaning no filtering by default, but says nothing about result size, ordering, or pagination behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The opening sentence is front-loaded and the Args block is scannable with one line per parameter. It is slightly verbose in repeating '(optional)' four times and could drop the redundant default restatement, but nothing is confusing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and all four parameters are fully documented. The remaining gap is operational: no mention of result limits or pagination for what is otherwise an unbounded list endpoint.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage at 0% (properties carry only titles and defaults), the description carries the full burden and does so: it specifies match semantics per parameter (case-insensitive substring for industry, exact match for tier and region), gives concrete example values, and explains the default for min_health_score. This is meaning the schema does not provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'List enterprise accounts in the knowledge graph', plus the scoping modifier 'optionally filtered'. It does not, however, distinguish itself from the sibling search_accounts, so an agent must infer which listing tool applies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description never says when to use this tool instead of search_accounts, get_account, or run_sparql_query, nor does it state any prerequisites or exclusions. Usage is only implied by the word 'List' and the optional filters.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_contacts_for_accountARead-only
List contacts (people) who work at a given account.
Args: account: The account identifier (e.g. "acct-atlasforge") or a name/substring (e.g. "AtlasForge"). role: Optional exact match on contact role, e.g. "Economic Buyer", "Champion", "Influencer", "User".
| Name | Required | Description | Default |
|---|---|---|---|
| role | No | ||
| account | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already state readOnlyHint=true and destructiveHint=false, so the agent knows this is a safe read. The description adds that role matching is exact and gives sample roles, but it does not describe return shape, pagination, or permission requirements beyond what the annotations and output schema already cover.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in one sentence, followed by a compact Args section. Every line adds usable information, and there is no redundant restatement of annotations or schema structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter read-only list tool with an output schema and safety annotations, the description is nearly complete. It covers both parameters with useful examples and does not need to explain return values because the output schema exists. The main missing piece is usage guidance versus sibling contact tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden for parameters and mostly succeeds. It explains that account can be an ID or a name/substring and that role is an optional exact-match filter with concrete examples. It does not clarify the default empty-string behavior for role or case sensitivity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a clear specific verb and resource: 'List contacts (people) who work at a given account.' It distinguishes the resource from sibling tools like get_contact or search_contacts by making the account scope explicit. It stops short of explicitly naming the sibling alternatives it should be preferred over.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit guidance on when to use this tool versus search_contacts, get_contact, or list_accounts. The account-scoped list purpose is implied by the tool name and parameter text, but the description never states when this is the right choice or when another sibling is better.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_sparql_queryARead-only
Run a read-only SPARQL SELECT or ASK query directly against the knowledge graph.
Use this for questions the higher-level account/contact tools can't answer,
e.g. joins, aggregations, or custom filters. The graph uses the crm:
prefix (http://example.org/crm#) for all classes and properties — call
get_graph_schema() first to see available classes and properties.
Only SELECT and ASK queries are permitted; INSERT/DELETE/DROP/LOAD/CREATE
are rejected. PREFIX crm: <http://example.org/crm#> is available
automatically but may also be declared explicitly.
Args: query: The SPARQL query text, e.g. "SELECT ?name ?arrUsd WHERE { ?a a crm:Account ; crm:name ?name ; crm:arrUsd ?arrUsd . } ORDER BY DESC(?arrUsd) LIMIT 5"
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint/destructiveHint, but the description adds substantive behavioral detail beyond them: only SELECT and ASK are permitted while INSERT/DELETE/DROP/LOAD/CREATE are rejected, and the crm: prefix is auto-injected but may be re-declared. This is exactly the extra context annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose followed by usage routing, constraints, prefix rules, and an example — each block earns its place. The multi-line example is long but directly teaches the allowed query shape, so it is not waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained; the description instead covers what matters for correct invocation — permitted query types, prefix handling, and the schema-discovery prerequisite. Nothing an agent needs is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the single parameter has no schema description, so the description must carry the burden — and it does, defining `query` as SPARQL text and supplying a concrete SELECT example with the crm: prefix. Only minor preconditions on parameter formatting remain unstated.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Run a read-only SPARQL SELECT or ASK query directly against the knowledge graph'), and explicitly positions itself against the higher-level account/contact siblings. An agent can distinguish it from search_accounts or get_contact without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use criteria ('questions the higher-level account/contact tools can't answer, e.g. joins, aggregations, or custom filters') and a prerequisite workflow step ('call get_graph_schema() first'). No inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_accountsARead-only
Search accounts by a keyword matched against name, industry, or account owner.
Args: keyword: Free-text keyword to search for (case-insensitive substring match).
| Name | Required | Description | Default |
|---|---|---|---|
| keyword | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. The description adds genuinely useful behavioral detail beyond that: the match is a case-insensitive substring search across three specific fields, which the annotations do not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded single sentence that states purpose and scope immediately. The Args block is slightly redundant with the opening sentence, but it adds the substring/case-insensitivity detail, so little is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with an output schema, the description is largely sufficient: purpose, matched fields, and matching semantics are all covered. Minor gaps (result limits or ordering) are excuseable given the output schema handles return values.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description must carry the keyword parameter, and it does: it defines it as free-text and specifies case-insensitive substring matching. That is meaningful semantics beyond the bare schema type.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (search) and resource (accounts), and narrows scope by naming the matched fields (name, industry, account owner). It does not explicitly distinguish itself from list_accounts, the closest sibling, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains what the search matches but gives no guidance on when to use it versus list_accounts or get_account, and no prerequisites or exclusions. Usage is only loosely implied by the word 'keyword'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_contactsARead-only
Search contacts by keyword matched against name, job title, or account name.
Args: keyword: Free-text keyword to search for (case-insensitive substring match). role: Optional exact match on contact role, e.g. "Economic Buyer", "Champion", "Influencer", "User".
| Name | Required | Description | Default |
|---|---|---|---|
| role | No | ||
| keyword | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered by structured data. The description adds genuinely useful matching semantics (case-insensitive substring match for keyword vs. exact match for role), but says nothing about result limits, pagination, or truncation behavior on a read search.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One front-loaded summary sentence followed by a short parameter block; nothing is padded. The Args section restates parameter names but adds real semantics alongside each, so it earns its space.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described, and the two parameters are well covered. What is missing is routing guidance against the many sibling search/lookup tools and any note on result-set size, which leaves the description minimally viable for an otherwise simple read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden and largely meets it: it explains that keyword is a free-text case-insensitive substring match and that role is an optional exact match, supplying example values ('Economic Buyer', 'Champion') that appear nowhere in the schema. Only the empty-string default for role is left unexplained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Search contacts') and names the three fields the keyword is matched against (name, job title, account name), which distinguishes it from sibling lookups like get_contact. It does not explicitly contrast itself with search_accounts or list_contacts_for_account, so sibling differentiation is implicit rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the search framing but there is no explicit when-to-use or when-not guidance, and no alternatives are named despite several overlapping siblings (list_contacts_for_account, get_contact, search_accounts). An agent must infer that this tool is for keyword discovery rather than targeted lookup.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
9 tool updates
v0.1.0- First observed
get_account - First observed
get_contact - First observed
get_graph_schema - First observed
get_graph_stats - First observed
list_accounts - First observed
list_contacts_for_account - First observed
run_sparql_query - First observed
search_accounts - First observed
search_contacts
TDQS
Scored across 9 tools
search_accounts (keyword) vs list_accounts (structured filters) both return account lists but the descriptions clarify the distinct filtering modes. Similarly search_contacts vs list_contacts_for_account are differentiated by scope. run_sparql_query has clear escape-hatch positioning relative to the higher-level tools.
All nine tools follow a consistent snake_case verb_noun pattern (get_graph_schema, search_accounts, list_accounts, get_contact, run_sparql_query, etc.). No mixed conventions or vague verbs.
Nine tools is well-scoped for a read-only CRM knowledge graph: two meta tools, three account tools, three contact tools, and a raw query escape hatch. Each earns its place.
Account and contact lifecycles are well covered for reading (list/search/get for both, plus schema, stats, and a raw SPARQL escape hatch for aggregations/joins). The surface is read-only by design, so no create/update/delete, and a bulk list-all-contacts view is missing but reachable via search_contacts or SPARQL.
Maintenance
Related MCP Connectors
API-first CRM for LLMs - contacts, companies, deals and activities over a native MCP server.
The HubSpot MCP Server acts as a bridge that enables AI assistants and Large Language Models to securely interact with HubSpot CRM data through natural conversation, without requiring users to understand complex API structures. It provides read-only access to standard CRM objects (contacts, companies, deals, tickets, products, invoices, and more) and their associations, secured via OAuth 2.0, allowing AI agents to perform tasks like summarizing deals, fetching company updates, and looking up record changes.
Marketo MCP server for AI. 130 tools to operate Marketo from Claude, Cursor, or ChatGPT.
MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA remote MCP server that connects Claude to a Twenty CRM workspace, enabling users to interact with CRM objects (People, Companies, Opportunities, and custom objects) through schema-driven tools for querying, creating, updating, and deleting records.1Apache 2.0
- FlicenseNot gradedqualityDmaintenanceRead-only MCP server that exposes the Poli Júnior Pipedrive CRM to Claude as composable tools.-
- AlicenseAqualityDmaintenanceA read-only MCP server that exposes HubSpot CRM data (contacts, deals, companies, quotes) to AI agents, enabling natural language queries.9MIT
- AlicenseNot gradedqualityBmaintenanceA local, read-only MCP server for Claude Desktop that provides 16 tools to search and read EspoCRM accounts, contacts, opportunities, and related emails via a strict allowlist.10 npmMIT