Skip to main content
Glama

mcp-toolkit-server

A custom Model Context Protocol (MCP) server exposing a small, composable registry of tools, resources, and prompts — the pattern behind "wrap it once, every agent gets access" enterprise tool integration.

CI Python License

Why this exists

MCP is the standardized layer that lets an agent framework (LangGraph, Claude Agent SDK, a custom orchestrator) discover and call tools without bespoke integration code per agent. I've built MCP server implementations against internal enterprise systems (knowledge bases, policy document APIs, compliance tools) in production; this project is a small, self-contained MCP server built from scratch to show the same pattern — a tool/resource/prompt registry with real JSON Schema contracts — in a form that's inspectable end to end.

Related MCP server: docsray-mcp

What it exposes

MCP defines three primitive types. This server implements all three:

Type

Name

What it does

Tool

calculate

Evaluates a numeric expression via a whitelisted AST walk (not eval)

Tool

search_knowledge_base

Keyword-overlap search over a bundled document set

Tool

text_stats

Character/word/sentence counts and estimated reading time

Resource

kb://documents

Lists available knowledge-base document names

Resource

kb://document/{name}

Fetches one document's full text (URI template)

Prompt

summarize_document

A reusable, parameterized prompt template

Installation

git clone https://github.com/varunram3232-glitch/mcp-toolkit-server.git
cd mcp-toolkit-server
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

Running the server

Over stdio (the transport Claude Desktop and most local MCP clients use):

mcp-toolkit-server

With the MCP Inspector, for interactive development:

mcp dev src/mcp_toolkit/server.py

Connecting it to Claude Desktop — add to your claude_desktop_config.json:

{
  "mcpServers": {
    "toolkit": {
      "command": "/absolute/path/to/.venv/bin/mcp-toolkit-server"
    }
  }
}

Example: calling it programmatically

Tools are callable through the FastMCP server object directly (useful for testing, or for embedding this server's logic in another Python process without a subprocess transport):

import asyncio
from mcp_toolkit.server import mcp

async def main():
    result = await mcp.call_tool("calculate", {"expression": "2 * (3 + 4) / 7"})
    print(result[0].text)  # "2.0"

    docs = await mcp.call_tool("search_knowledge_base", {"query": "tool schema"})
    print(docs[0].text)

asyncio.run(main())

Design decisions

  • A real AST walk for calculate, never eval. Tool arguments come from a language model's interpretation of a user prompt — treating that as trusted input to eval() is a textbook injection risk. calculator.py parses the expression into an AST and only evaluates a fixed whitelist of numeric operators; anything else (__import__, attribute access, comprehensions, name lookups) is rejected before it ever executes.

  • The description field is the real interface. A tool's JSON Schema tells a model what arguments are valid; the natural-language description is what tells it when to call the tool at all. Every tool and the server's top-level instructions are written to be specific about that ("use calculate instead of computing it yourself") rather than a generic one-liner.

  • Resources vs. tools, used for what each is for. The knowledge base is exposed as a resource (kb://document/{name}) so a client can attach a specific document to context deliberately (like a file picker), separately from search_knowledge_base, which is a tool the model decides to invoke based on the conversation. Collapsing these into one mechanism is a common MCP design mistake this repo deliberately avoids.

  • Dependency-free knowledge base. Search here is keyword overlap, not embeddings — this repo is about the MCP server/tool-registry pattern, not retrieval quality. See agentic-rag-assistant for a real embedding-based RAG pipeline that a production version of this tool would call into.

Testing

pip install -e ".[dev]"
pytest -v
ruff check src tests

39 tests, split across two layers:

  • Unit tests for the pure logic (test_calculator.py, test_knowledge_base.py, test_text_stats.py) — including a dedicated set of injection-attempt expressions (__import__, open(...), list comprehensions) that the calculator must reject.

  • Protocol-level integration tests (test_server_integration.py) that call the real FastMCP server object's list_tools / call_tool / list_resources / read_resource / list_prompts / get_prompt — verifying the MCP contract itself, not just the functions behind it.

Project structure

src/mcp_toolkit/
├── server.py              # FastMCP instance — tool/resource/prompt registration
├── tools/
│   ├── calculator.py        # AST-walking safe expression evaluator
│   ├── knowledge_base.py    # In-memory document store + keyword search
│   └── text_stats.py        # Text analysis
└── data/                    # Bundled knowledge-base documents

Roadmap

  • Streamable HTTP transport for remote deployment

  • Auth middleware example (API key / OAuth) for a non-stdio deployment

  • A tool that calls out to agentic-rag-assistant for embedding-based search

License

MIT — see LICENSE.

Available Tools

3 tools
calculateA

Evaluate a numeric arithmetic expression and return the result.

Supports +, -, *, /, //, %, ** and parentheses. Use this for any arithmetic instead of computing it yourself — language models are unreliable at multi-digit math.

Args: expression: A numeric expression, e.g. "2 * (3 + 4) / 7".

ParametersJSON Schema
NameRequiredDescriptionDefault
expressionYes

TDQS

A4.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must disclose behavioral traits. It states the tool evaluates expressions and returns results, and lists supported operators, but does not mention error handling (e.g., invalid expressions, division by zero) or confirm it is non-destructive. This is adequate but leaves some gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (three sentences plus an Args line) and front-loaded with the core purpose. Every sentence earns its place: purpose, supported operators, usage guidance, and parameter explanation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with one parameter and no output schema, the description covers purpose, usage, parameter semantics, and supported operators. It could mention error cases, but overall it is sufficiently complete for an agent to select and invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides only the parameter name and type (string). The description adds meaningful semantics by explaining 'A numeric expression' and giving a concrete example '2 * (3 + 4) / 7'. This fully compensates for the 0% schema description coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states precisely what the tool does: 'Evaluate a numeric arithmetic expression and return the result.' It uses a specific verb and resource, and the supported operators distinguish it from sibling tools like search_knowledge_base and text_stats.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit usage guidance is provided: 'Use this for any arithmetic instead of computing it yourself — language models are unreliable at multi-digit math.' This clearly tells the agent when to use the tool and implies not to use it for non-arithmetic operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_knowledge_baseA

Search the bundled knowledge base for passages relevant to a query.

Args: query: Natural-language search query. top_k: Maximum number of results to return (default 3).

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYes
top_kNo

TDQS

A4/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It only states the basic search function and does not mention whether the operation is read-only, any side effects, or limitations. This is a gap for a tool whose safety profile is unknown.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured: a single leading sentence followed by a clean Args section. Every word earns its place, with no redundant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple, but the description lacks details about the return format or the scope of the knowledge base. Since there is no output schema, a bit more context on what 'passages' look like or how results are ordered would improve completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description explicitly explains both parameters: 'query' as a natural-language search query and 'top_k' as the maximum number of results. This fully compensates for the 0% schema coverage, adding meaning beyond the raw types and default.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states exactly what the tool does: 'Search the bundled knowledge base for passages relevant to a query.' It uses a specific verb ('search') and target resource ('bundled knowledge base'), and it is clearly distinct from sibling tools like 'calculate' and 'text_stats'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies clear usage context: use this tool to query the knowledge base with natural language. While it does not explicitly list alternatives or exclusions, the context is self-evident and sufficient for a simple search tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

text_statsA

Compute character count, word count, sentence count, and estimated reading time for a piece of text.

Args: text: The text to analyze.

ParametersJSON Schema
NameRequiredDescriptionDefault
textYes

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden of behavioral disclosure. It lists the computed outputs and the text input, but does not address edge cases (e.g., empty text), output structure, or side effects. For a pure computation tool, this is adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence defining purpose, followed by a minimal argument description. It is front-loaded with the function's goal and avoids redundancy with the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple with one parameter and no output schema. The description covers the operation but omits details about the return format, which an agent would need to interpret the result. This is a notable gap, though the listed metrics hint at the output shape.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema only provides the parameter name and type (string). The 'Args' section adds a plain-language explanation ('The text to analyze'), which clarifies the purpose of the single parameter. Since schema coverage is 0%, the description compensates effectively.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses the specific verb 'Compute' and enumerates exact metrics (character count, word count, sentence count, reading time), making the tool's function unambiguous. It clearly distinguishes from siblings by domain (text analysis vs calculation/search).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is for analyzing text passages, which is clear enough given unrelated siblings. However, there is no explicit 'when not to use' or mention of alternative tools, so it stops short of full guidance.

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.

  1. 3 tool updatesv0.1.0
    • First observedcalculate
    • First observedsearch_knowledge_base
    • First observedtext_stats

TDQS

A4.1/5.0

Scored across 3 tools

Disambiguation5/5

Each tool performs a completely distinct function: arithmetic evaluation, knowledge base search, and text statistics. There is no overlap or ambiguity between them.

Naming Consistency4/5

Names are mostly verb_noun (search_knowledge_base) or single verb (calculate), but text_stats breaks the pattern as noun_noun. Still, all are snake_case and clearly readable.

Tool Count4/5

With 3 tools, the server is on the low end of typical scope but appropriate for a small utility toolkit. Each tool is useful and not redundant.

Completeness3/5

The server lacks a coherent domain, covering arithmetic, knowledge search, and text stats. While each tool is self-contained, the set feels arbitrary and could benefit from more utility categories.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    C
    quality
    D
    maintenance
    An MCP server that provides text conversion, formatting, and analysis functions, which can be directly integrated into the development workflow.
    43
    2
    Apache 2.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server providing 9 tools for coding agents to search technology, development, open source, and cybersecurity topics, with support for multiple channels.
    MIT