Skip to content
snowkit

kits / connector-starter

v1.0.0

Connector Starter

A minimal, tested Model Context Protocol server in TypeScript and Python, with one example tool and security notes.

connector-starterREADME.md

Markdown · 10.1 KB

Connector Starter

Version 1.0.0

A small, working Model Context Protocol (MCP) server in two languages: TypeScript and Python. Each starter has one useful example tool, tests that run without a network, and a README. Copy the folder for your language, rename it and start adding your own tools.

MCP is an open protocol that lets an assistant or agent call tools, read resources and use prompts that live outside the app it runs in. You write a server once, and any client that speaks MCP can connect to it.

Who it's for

  • Developers who want to expose an API, a database query or an internal script to their assistant or coding agent
  • Teams that need a clean, tested starting point instead of copying snippets from several places
  • Anyone who prefers to read a small, complete example before reading a specification

You should be comfortable with a terminal and with either Node.js or Python.

How to use it in 5 minutes

  1. Pick a language. Copy typescript/ or python/ to where your project lives.
  2. Install and test it. TypeScript: npm install, npm run build, npm test. Python: create a virtual environment, pip install -e ".[dev]", pytest.
  3. Open the server in the MCP Inspector (see "Testing with the MCP Inspector" below) and call text_stats by hand.
  4. Add the server to your MCP client using the config in "Connecting to a client".
  5. Read "Adding a second tool" and "Security notes for tools" before you write your own.

File map

FileWhat it is
README.mdThis guide: running, connecting, extending, testing and securing the starters
LICENSE.txtMIT licence
CHANGELOG.mdRelease history
typescript/README.mdSetup, scripts, tool reference and an example second tool for the TypeScript starter
typescript/package.jsonDependencies and the build, start, dev, typecheck and test scripts
typescript/tsconfig.jsonCompiler settings (ES2022, NodeNext modules, strict mode)
typescript/src/server.tscreateServer() with the text_stats tool and its zod schemas
typescript/src/index.tsEntry point that connects the server to stdio
typescript/test/server.test.tsTests using the SDK client over an in-memory transport
python/README.mdSetup, tool reference and an example second tool for the Python starter
python/pyproject.tomlPackage metadata, dependencies, dev extras and the console script
python/src/connector_starter/__init__.pyPackage exports
python/src/connector_starter/__main__.pyEnables python -m connector_starter
python/src/connector_starter/server.pycreate_server() with the text_stats tool and main()
python/tests/test_server.pyTests using mcp.Client connected in-process

The example tool

Both starters register the same tool, so a client sees identical behaviour whichever language you run.

text_stats counts the words, characters and lines in a piece of text and estimates the reading time.

ArgumentTypeRules
textstringRequired. Up to 100,000 characters.
words_per_minuteintegerOptional. 50 to 1000. Defaults to 200.

Example result for "Hello world\nSecond line here":

{ "words": 5, "characters": 28, "lines": 2, "reading_time_seconds": 2 }

It is deliberately simple: deterministic, no network, no secrets. That makes it a good template for testing and a safe thing to leave in while you build.

Running the starters

TypeScript (Node.js 20 or newer):

cd typescript
npm install
npm run build
npm start

Python (3.10 or newer), macOS and Linux:

cd python
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
connector-starter

On Windows, activate with .\.venv\Scripts\Activate.ps1 instead.

Both servers speak MCP over stdio. Started by hand, they wait silently for input. That is normal: a client normally starts the process for you.

Connecting to a client

Most desktop and editor clients read a JSON config with an mcpServers object. The file name and location differ by client, so check its documentation for where the file lives. The shape is the same. Always use absolute paths, because the client may start the server from a different working directory.

TypeScript (after npm run build):

{
  "mcpServers": {
    "connector-starter": {
      "command": "node",
      "args": ["/absolute/path/to/connector-starter/typescript/dist/index.js"]
    }
  }
}

Python, macOS and Linux (point at the virtual environment so the right packages load):

{
  "mcpServers": {
    "connector-starter": {
      "command": "/absolute/path/to/connector-starter/python/.venv/bin/connector-starter",
      "args": []
    }
  }
}

Python on Windows (backslashes must be doubled in JSON):

{
  "mcpServers": {
    "connector-starter": {
      "command": "C:\\projects\\connector-starter\\python\\.venv\\Scripts\\python.exe",
      "args": ["-m", "connector_starter"]
    }
  }
}

If your server needs settings such as an API key, most clients accept an env object next to args. Keep real values in that local config or in your secret store, never in the repository.

After editing the config, restart the client or reload its MCP servers. If the tool does not appear, check the client's MCP log first. The usual causes are a relative path, a missing build, or a virtual environment that was never installed into.

Adding a second tool

Each language README shows a complete second tool (slugify). The pattern is the same in both:

  1. Write the logic as a plain function you can unit test.
  2. Register it inside createServer() or create_server() with a clear name, a one-sentence description and a strict input schema.
  3. Add annotations: readOnlyHint for tools that change nothing, destructiveHint for tools that delete or overwrite, openWorldHint for tools that reach the internet.
  4. Add tests: one for the plain function, one call through the in-memory client and one invalid-input case.
  5. Rebuild (TypeScript) and reload the server in your client.

Naming tips: use short snake_case verbs or nouns (search_orders, get_invoice). Write the description for the model that will read it: say what the tool does, what it returns and when not to use it. Keep the number of tools small; many similar tools make selection worse.

Testing with the MCP Inspector

The MCP Inspector is the official tool for poking at a server by hand. It runs with npx, so nothing needs to be installed globally.

Open the browser interface:

cd typescript
npx @modelcontextprotocol/inspector node dist/index.js
cd python
npx @modelcontextprotocol/inspector .venv/bin/connector-starter

On Windows, use .venv\Scripts\connector-starter.exe for the Python command. The Inspector prints a local URL. Open it, press Connect, go to Tools, list the tools and run text_stats with your own text. Try a words_per_minute of 5 to see how a validation error is reported.

For scripts and CI, the Inspector also has a command-line mode:

npx @modelcontextprotocol/inspector --cli node dist/index.js --method tools/list
npx @modelcontextprotocol/inspector --cli node dist/index.js --method tools/call --tool-name text_stats --tool-arg "text=one two three"

The automated tests in each starter cover the same ground without starting a process, so run npm test or pytest on every change and use the Inspector for exploration.

Security notes for tools

A tool is code that an agent can run on your behalf, often with your permissions. Treat every argument as untrusted input, even when you trust the person using the client: the arguments are chosen by a model, and the model can be steered by content it reads.

  • Validate input. Give every argument a type, a length or range limit and, where it fits, an enum or pattern. The schema is enforced before your code runs; add checks in code for anything a schema cannot express, such as "this path must stay inside this folder".
  • Least privilege. Give the server only the access it needs: a read-only database user, a scoped API token, one directory instead of the whole disk. Split read and write actions into separate tools, and mark write tools with destructiveHint so clients can ask for confirmation.
  • Never return secrets. Do not echo tokens, keys, connection strings or full environment variables in results or error messages. Return only the fields the caller needs. Remember that results are shown to the model and may be logged by the client.
  • Set timeouts. Put a timeout on every network call, subprocess and query, and cap the size of what you return. A tool that hangs blocks the whole conversation.
  • No shell strings. If a tool must run a program, pass arguments as a list and never build a shell command from input. Never pass input to eval or similar.
  • Watch paths and URLs. Resolve file paths and reject anything outside an allowed root. For URLs, allow-list hosts and block internal addresses so the tool cannot be used to reach your private network.
  • Keep stdout clean. On stdio, stdout is the protocol channel. Log to stderr or to a file.
  • Pin and review dependencies. Commit your lockfile in your own project, keep the SDK up to date and read the release notes before major upgrades.

Package versions

This release was built and tested against:

StarterPackageVersion range
TypeScript@modelcontextprotocol/sdk^1.32.1
TypeScriptzod^4.6.7
TypeScripttypescript (dev)^7.0.2
Pythonmcp>=2.3.0,<3

No lockfile is included, so npm install and pip install resolve the newest matching versions. Commit the lockfile your install creates so your builds stay repeatable.

A note on limits

These are starters, not frameworks. They use stdio only; remote hosting over Streamable HTTP, authentication, rate limiting and deployment are out of scope. The security notes reduce risk but cannot make a tool safe on their own; review any tool that writes data or touches the network before you connect it to an agent. MCP and its SDKs change quickly, so check the release notes when you upgrade.

Licence

MIT License. See LICENSE.txt.