Metadata-Version: 2.4
Name: localmcplib
Version: 0.1.3
Summary: Reusable foundations for local stdio MCP servers.
Author: Demian Brecht
Author-email: Demian Brecht <dbrecht@salesforce.com>
License-Expression: Apache-2.0
License-File: LICENSE.txt
Classifier: Development Status :: 3 - Alpha
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Dist: aiosqlite>=0.22.1 ; extra == 'all'
Requires-Dist: fastmcp>=4.0.5 ; extra == 'all'
Requires-Dist: httpx2>=2.13.0 ; extra == 'all'
Requires-Dist: keyring>=25.7.0 ; extra == 'all'
Requires-Dist: langchain-anthropic>=1.7.2 ; extra == 'all'
Requires-Dist: langchain-core>=1.6.4 ; extra == 'all'
Requires-Dist: langchain-openai>=1.6.3 ; extra == 'all'
Requires-Dist: langfuse>=4.15.4,<5 ; extra == 'all'
Requires-Dist: langgraph-checkpoint-sqlite>=3.1.1 ; extra == 'all'
Requires-Dist: pydantic>=2.13.5 ; extra == 'all'
Requires-Dist: structlog>=26.1.0 ; extra == 'all'
Requires-Dist: httpx2>=2.13.0 ; extra == 'llm'
Requires-Dist: langchain-anthropic>=1.7.2 ; extra == 'llm'
Requires-Dist: langchain-openai>=1.6.3 ; extra == 'llm'
Requires-Dist: structlog>=26.1.0 ; extra == 'observability'
Requires-Dist: langchain-core>=1.6.4 ; extra == 'sandbox'
Requires-Dist: pydantic>=2.13.5 ; extra == 'sandbox'
Requires-Dist: keyring>=25.7.0 ; extra == 'secrets'
Requires-Dist: fastmcp>=4.0.5 ; extra == 'server'
Requires-Dist: httpx2>=2.13.0 ; extra == 'server'
Requires-Dist: keyring>=25.7.0 ; extra == 'server'
Requires-Dist: langchain-anthropic>=1.7.2 ; extra == 'server'
Requires-Dist: langchain-openai>=1.6.3 ; extra == 'server'
Requires-Dist: structlog>=26.1.0 ; extra == 'server'
Requires-Dist: fastmcp>=4.0.5 ; extra == 'telemetry'
Requires-Dist: langfuse>=4.15.4,<5 ; extra == 'telemetry'
Requires-Dist: structlog>=26.1.0 ; extra == 'telemetry'
Requires-Dist: aiosqlite>=0.22.1 ; extra == 'workflows'
Requires-Dist: langgraph-checkpoint-sqlite>=3.1.1 ; extra == 'workflows'
Requires-Dist: structlog>=26.1.0 ; extra == 'workflows'
Maintainer: Demian Brecht
Maintainer-email: Demian Brecht <dbrecht@salesforce.com>
Requires-Python: >=3.12
Project-URL: Homepage, https://github.com/salesforce-misc/localmcplib
Project-URL: Repository, https://github.com/salesforce-misc/localmcplib
Project-URL: Issues, https://github.com/salesforce-misc/localmcplib/issues
Provides-Extra: all
Provides-Extra: llm
Provides-Extra: observability
Provides-Extra: sandbox
Provides-Extra: secrets
Provides-Extra: server
Provides-Extra: telemetry
Provides-Extra: workflows
Description-Content-Type: text/markdown

# localmcplib

`localmcplib` is a Python foundation for local MCP servers that run over
stdio. It packages the infrastructure that tends to be repeated across serious
local servers while leaving tools, prompts, application schemas, and product
behavior to each application.

The published distribution is `localmcplib`; the Python import package is
`localmcp`.

## Introduction

A local MCP server can start as a few tool functions, but production use adds a
surprising amount of non-domain work: stdout and stderr must remain clean for
JSON-RPC, credentials need safe lookup boundaries, configuration must compose
across servers, model connections need deployment-independent routing, and
long-running operations need lifecycle and recovery support. Model-controlled
local commands also need an actual security boundary.

`localmcplib` owns these reusable mechanics while consuming servers continue
to own their schemas, tools, service clients, prompts, and authorization
policy.

## Quickstart

Install the integrated server capability:

```console
uv add 'localmcplib[server]'
```

The following complete `hello.py` registers one tool and runs it as a FastMCP
stdio server. `STDIOServer` loads and validates localmcplib's configuration;
applications only need a parser when they add their own configuration fields.

```python
from fastmcp.tools import tool

import localmcp

NAME = "hello-mcp"


@tool
def hello(name: str = "world") -> str:
    return f"Hello, {name}!"


# STDIOServer owns an application runtime so durable tasks and other resources
# share its startup/shutdown lifecycle. Hello has no such work, so this runtime
# intentionally does nothing.
class NoopRuntime:
    def __init__(self, *_args: object, **_kwargs: object) -> None:
        pass

    async def start(self) -> None:
        pass

    async def close(self) -> None:
        pass


server = localmcp.STDIOServer(
    name=NAME,
    tools=[hello],
    runtime_factory=NoopRuntime,
)

if __name__ == "__main__":
    localmcp.main(server)
```

Create `~/.config/localmcp/localmcp.toml`:

```toml
schema_version = 1

[llm]
backend = "openai_compatible"
base_url = "https://llm.example.test/v1"

[secrets.llm_api_key]
env_vars = ["HELLO_LLM_API_KEY"]
```

Then run the server from an MCP client with `uv run python hello.py`. The
integrated server loads configuration and secrets, creates the model and
telemetry boundaries, owns the application runtime, registers the tool, and
serves it over stdio without writing logs to the protocol streams.

## Features

### Stdio MCP server composition

`localmcp.STDIOServer` assembles a FastMCP application from a server name, tool
list, and runtime factory. It owns startup and shutdown ordering, shared config
validation, secrets, model and telemetry wiring, per-server state paths,
file-only logging, and silent failure handling for stdout/stderr-safe operation.
Applications with additional configuration fields may supply an optional typed
`config_parser`; its result is passed to the runtime factory and lifespan.

### Shared configuration and paths

One schema-versioned, XDG-aware `localmcp.toml` document provides shared
defaults. `[server.<name>]` recursively overlays those defaults for one logical
server. Applications choose the config file boundary and validate their own
effective schema; state, cache, and logs remain isolated per server.

See [docs/configuration.md](docs/configuration.md) for the document contract.

### Secrets

Applications declare logical secret names in configuration without storing
secret values there. Resolution checks declared environment variables first,
then the operating-system keyring. Global secrets use the shared `localmcp`
keyring service; server-private secrets use `localmcp:<server-name>`. Resolved
values are redacted from string representations and errors.

### LLM routing

Applications select logical model IDs independently of deployment routing. An
`openai_compatible` deployment can send models through a shared LiteLLM-style
endpoint, while a `native` deployment routes the same IDs to OpenAI or
Anthropic credentials. Gateway protocol dialect and native provider are
separate model properties, so switching deployment does not require changing
application model roles.

### Sandboxing

The sandbox API provides bounded command execution with explicit filesystem
roots, a clean environment, output and time limits, process-group cleanup, and
network access disabled by default. The current implementation uses macOS
Seatbelt; the portable interface leaves room for a future Linux backend.

### Durable workflows

The workflow package supplies LangGraph lifecycle management and a generic
SQLite operation catalog with ownership checks, recovery, worker leases,
heartbeats, cancellation, and durable tool-call budgets. Applications retain
responsibility for domain state, idempotency, and consequential side effects.

### Observability

Structured logs are written to files only so they cannot corrupt stdio
JSON-RPC. Optional Langfuse integration adds failure-isolated tracing and
FastMCP middleware. Model and tool payload attributes are suppressed by
default. Set `LOCALMCP_LANGFUSE_CAPTURE_PAYLOADS=true` to capture model prompts,
model responses, tool arguments, and tool results. This opt-in can send secrets,
repository content, and other sensitive data to Langfuse; enable it only when
the configured Langfuse project is an approved destination for those payloads.

## Capability extras

Install only what an application uses:

| Extra | Capability |
| --- | --- |
| `server` | Integrated FastMCP stdio application composition |
| `secrets` | OS-keyring secret resolution |
| `llm` | OpenAI-compatible and native OpenAI/Anthropic models |
| `sandbox` | Portable sandbox API and macOS Seatbelt implementation |
| `observability` | Structured file logging |
| `telemetry` | Langfuse and FastMCP telemetry integration |
| `workflows` | Durable LangGraph and SQLite workflow foundations |
| `all` | Every optional capability |

For example:

```console
uv add 'localmcplib[server,sandbox,workflows]'
```

## Status

The API is alpha and may change as additional local MCP servers adopt the
library.

## Development

Install the complete development environment and run the repository checks:

```console
make install
make ci
make build
```

Run `make help` to list the individual formatting, linting, type-checking,
testing, coverage, build, and cleanup targets.
