Overview
An MCP server is not just “some code running on a machine.” It’s a structured way to expose implemented capabilities through the Model Context Protocol once running. Each server starts with a specification (the manifest describing its tools, resources, and prompts), has implementation code that fulfills that specification, and can be turned into a running instance. Pylee helps manage that lifecycle: versioning, registries, runtime secret injection, access control, monitoring, and audit.Core MCP Server Building Blocks
Every MCP server defines what it can do using three primitives:-
Tools — actions the client or agent can perform. Each tool has a schema for inputs and outputs (e.g.
sendEmail(to, subject, body)
orcreateCalendarEvent(title, start, end)
). -
Resources — structured data sources available to clients, identified by URIs. (e.g.
file:///notes/project.md
,calendar://events/2025
, orvault://secret/{name}
.) -
Prompts — reusable workflows or templates that guide how tools and resources are used together.
(e.g.triageSupportTicket(ticket_id)
orplanVacation(destination, duration)
).
Server Hierarchy and Ownership
Everything in Pylee belongs to an organization, which is the top level entity. Organization → Servers → Server Versions → Deployments- Organizations own servers, registries, deployments, variables, secrets, and memberships.
- Servers belong to exactly one organization and live under a namespace like
@org-slug/server-name
. - Server versions are immutable snapshots of a server, tied back to the organization.
- Deployments are running instances of specific server versions.
- Registries are owned by organizations. They act as curated collections of servers for teams or projects.
Relationship model
Talking about MCP “servers”
The word server inevitably comes up in conversations about MCP in a few nuanced but important ways. To avoid confusion, here’s how we think of this at Pylee:-
Server specification — a manifest file that describes what the server can do (its tools, resources, and prompts) and configuration (connection type, transportation type, and arguments). Think of this as a blueprint.
Example: a JSON manifest listing anissue:create
tool and aprojects://roadmap
resource via a remote HTTP server. -
Server implementation — the actual code, package, or container that fulfills the specification. This is what you, as a developer, write.
Example: a Python package that knows how to create issues in GitHub. -
Running instance — a live process that clients can connect to. This is the “server” in the classic sense.
Example: a process running on your laptop, or an HTTP server hosted in your cloud.
Deployment, Connection, and Transport
Another common source of confusion while speaking about MCP servers is confounding the deployment, connection type, and transportation protocol. We like to separate into three distinct questions:-
Deployment / Location — Where is the server running?
- Local: runs on the same machine as the client (e.g. your IDE spawns it).
- Remote: runs elsewhere (a container, VM, or hosted service).
-
Connection / Entry Point — How do I reach it?
Think of this as the connection method, startup mode, or endpoint type.- Package (start on demand): the client starts a child process server by running a command.
Example:["python", "-m", "my_mcp"]
- Remote (prerunning): the client connects to a server already running at a URL.
Example:https://my-server.acme.com
- Package (start on demand): the client starts a child process server by running a command.
-
Transport — Once connected, how do messages flow?
- stdio: when one program starts another, they talk through built-in text channels (stdin/stdout) - like how terminals and editors communicate with tools they launch.
- http/sse: network-friendly web protocols; common in production.
Use case | Location | Entry point | Transport | How the client connects | Typical fit |
---|---|---|---|---|---|
Editor/CLI local tool | Local | Package (start command) | STDIO | Client launches the process; no network port | Local file access, quick iteration |
Local web testing | Local | Remote (URL on localhost) | HTTP/SSE | Client connects to http://localhost:PORT | Test the same server you’ll deploy |
Team/shared service | Remote | Remote (public/internal URL) | HTTP/SSE | Client connects to URL (often via registry) | Production and shared integrations |
- A local package is often paired with stdio, but could also spawn an HTTP/SSE server that the client then connects to.
- A remote almost always uses HTTP/SSE, since
stdio
only works with parent/child processes. - A pre-running server can still be on your local machine at
http://localhost
- useful when testing servers during development.
How Servers Map into Pylee
In Pylee, a server is the top level MCP definition your organization owns. Servers specs evolve through server versions, which are immutable snapshots that declare:- Entry point — how clients connect (either a Package launched locally via STDIO, or a Remote at a URL over HTTP/SSE).
- Capabilities — the tools, resources, and prompts exposed.
- Placeholders — configuration keys (like
API_KEY
,BASE_URL
) that Pylee fills in at runtime.
Configuration: Connection Type, Versions, & Placeholders
To create an MCP server spec, you first instantiate a server version. While configuring arguments, server versions may declare placeholders (like{API_KEY}
, {BASE_URL}
) instead of hardcoding values. At runtime, Pylee fills in these placeholders with the right values.
Versioning
Servers evolve through versions. A server version first declares the appropriate connection or entry point type(s). e.g. Package or Remote and associated approrpiate runtime or header arguments. Each version is immutable and should be pinned for consistency.- Versions are editable until published; after publish they’re immutable.
- Any alphanumeric string is accepted as a version label.
- Best practice: use semantic versioning (
1.2.0
) to signal breaking, minor, and patch changes. - Pinning makes CI, IDEs, and agents more reliable.
- Immutable versions make rollbacks simple.
Placeholders
Declare placeholders (e.g.,API_KEY
, BASE_URL
) in the Server Version. Pylee resolves them at runtime using the following order for runtime:
- Registry values — highest priority, often used to scope per team or project.
- Organization values — defaults shared across the org.
Visibility and Sharing
Servers can be:- Private — default. Visible only inside your organization and its registries.
- Public — listed in the Pylee Marketplace, and optionally mirrored to Anthropic’s global registry.
Deployment and running instances
Once you’ve written your implementation code (your repo), the next question is: where do I want this code to run?There are three main options. Each one ties back to how MCP defines a server in the spec (as a package or a remote).
1. Run locally (on your laptop)
- Where it runs: directly on your machine.
- How it works:
- If the server is a package (stdio), the client launches it as a local process. No network port is used — the client and server just talk through stdin/stdout.
- If the server is a remote (HTTP/SSE), you can still run it locally on a port like
http://localhost:3000
. Even though it’s on your laptop, you configure it as a remote in the server spec.
- When to use it: quick iteration, debugging, or servers that need access to your local files.
- How to connect: usually via direct connect in your IDE or client. You can also use a registry if you want to share consistent settings across multiple clients.
2. Run in your own infrastructure
- Where it runs: in your cloud or on-prem environment (e.g., AWS, GCP, Azure, or your own servers).
- How it works:
- Always configured as a remote (HTTP/SSE).
- The same process you tested on
localhost:3000
during development can be deployed behind your own public or internal URL. Update the server version in Pylee to point to the new URL.
- When to use it: when your team already manages hosting and scaling.
- How to connect: recommended via registries (for audit and governance), but direct connect is still possible for testing.
3. Run on Pylee (hosted deployment)
- Where it runs: Pylee builds and runs your implementation for you in a managed environment.
- How it works:
- Pylee deploys it as a remote (HTTP/SSE).
- You don’t need to assign a URL — Pylee issues a secure one automatically.
- Variables and secrets are injected safely at runtime.
- When to use it: when you want a production-ready server without setting up infrastructure.
- How to connect: usually through registries, which add visibility, approvals, and version pinning.
Localhost during development
When you’re building a server that will eventually be a remote, it’s normal to run it first onhttp://localhost:3000
.
- Create or select a server version.
- Register
localhost:3000
as the remote. - Run your implementation code locally and connect to it.
- Optionally use a tool like ngrok if you need to expose it temporarily for external clients.
- Later, swap the remote URL for a production endpoint (your own infra or Pylee-hosted).
- A “remote” just means “a server with an HTTP/SSE endpoint.” That endpoint can point to localhost during dev or a hosted URL in production.
- A stdio server is always a package and never runs on a port.
Pylee Usage
Where the server runs (local, your infra, or Pylee) is separate from how to use through Pylee. There are two ways:- Direct connection — attach to one server at a time. Simple for testing or focused tasks.
- Registry connection — attach through a registry, which can include many servers. Registries also provide approvals, pinning, and audit. This is the recommended way for production.
Putting it together
A common path looks like this:- Write your implementation code.
- Run it locally:
- as a package (stdio), or
- as a remote (HTTP/SSE) bound to
localhost:3000
.
- Create a server version in Pylee, marking it as a package or remote.
- Promote the same implementation:
- run it in your own infra and update the remote URL, or
- deploy on Pylee and use the URL provided for you.
- Pin the version in a registry so teams connect to the same server securely with variables and secrets resolved.