mcp-stdio-proxy 1.0.0b3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcp_stdio_proxy-1.0.0b3/.gitignore +35 -0
- mcp_stdio_proxy-1.0.0b3/PKG-INFO +165 -0
- mcp_stdio_proxy-1.0.0b3/README.md +144 -0
- mcp_stdio_proxy-1.0.0b3/pyproject.toml +49 -0
- mcp_stdio_proxy-1.0.0b3/src/mcp_stdio_proxy/__init__.py +1 -0
- mcp_stdio_proxy-1.0.0b3/src/mcp_stdio_proxy/main.py +73 -0
- mcp_stdio_proxy-1.0.0b3/tests/test_main.py +61 -0
- mcp_stdio_proxy-1.0.0b3/tests/test_placeholder.py +6 -0
- mcp_stdio_proxy-1.0.0b3/uv.lock +274 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
.venv/
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
.ruff_cache/
|
|
7
|
+
*.egg-info/
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
|
|
11
|
+
# Node
|
|
12
|
+
node_modules/
|
|
13
|
+
.pnpm-store/
|
|
14
|
+
*.tsbuildinfo
|
|
15
|
+
|
|
16
|
+
# IDE
|
|
17
|
+
.vscode/
|
|
18
|
+
.idea/
|
|
19
|
+
|
|
20
|
+
# OS
|
|
21
|
+
.DS_Store
|
|
22
|
+
Thumbs.db
|
|
23
|
+
|
|
24
|
+
# Local state
|
|
25
|
+
_backup/
|
|
26
|
+
.worktrees/
|
|
27
|
+
*.log
|
|
28
|
+
.env
|
|
29
|
+
.env.*
|
|
30
|
+
!.env.example
|
|
31
|
+
coverage/
|
|
32
|
+
*.lcov
|
|
33
|
+
|
|
34
|
+
# Code review graph
|
|
35
|
+
.code-review-graph/
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mcp-stdio-proxy
|
|
3
|
+
Version: 1.0.0b3
|
|
4
|
+
Summary: Thin stdio-to-HTTP forwarder for MCP agents lacking HTTP support
|
|
5
|
+
Project-URL: Homepage, https://github.com/n24q02m/mcp-core
|
|
6
|
+
Project-URL: Repository, https://github.com/n24q02m/mcp-core
|
|
7
|
+
Project-URL: Issues, https://github.com/n24q02m/mcp-core/issues
|
|
8
|
+
Author-email: n24q02m <quangminh2422004@gmail.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: mcp,proxy,stdio,transport
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
18
|
+
Requires-Python: ==3.13.*
|
|
19
|
+
Requires-Dist: httpx>=0.28.1
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# mcp-core
|
|
23
|
+
|
|
24
|
+
Unified MCP Streamable HTTP 2025-11-25 transport, OAuth 2.1 Authorization
|
|
25
|
+
Server, lifecycle management, install automation, and shared embedding
|
|
26
|
+
daemon for the n24q02m MCP ecosystem.
|
|
27
|
+
|
|
28
|
+
`mcp-core` is the **functional successor** to the archived
|
|
29
|
+
[`mcp-relay-core`](https://github.com/n24q02m/mcp-relay-core). All crypto,
|
|
30
|
+
storage, OAuth, relay, and schema modules from `mcp-relay-core` ship under
|
|
31
|
+
the same paths in `mcp-core` (1:1 superset), so downstream MCP servers can
|
|
32
|
+
migrate with a pure import + dependency rename. See
|
|
33
|
+
[`docs/migration-from-mcp-relay-core.md`](docs/migration-from-mcp-relay-core.md)
|
|
34
|
+
for the rename table.
|
|
35
|
+
|
|
36
|
+
## Packages
|
|
37
|
+
|
|
38
|
+
| Package | Language | Registry | Install |
|
|
39
|
+
|---------|----------|----------|---------|
|
|
40
|
+
| [`packages/core-py`](packages/core-py) | Python 3.13 | PyPI: [`n24q02m-mcp-core`](https://pypi.org/project/n24q02m-mcp-core/) | `pip install n24q02m-mcp-core` |
|
|
41
|
+
| [`packages/core-ts`](packages/core-ts) | TypeScript / Node 24 | npm: [`@n24q02m/mcp-core`](https://www.npmjs.com/package/@n24q02m/mcp-core) | `bun add @n24q02m/mcp-core` |
|
|
42
|
+
| [`packages/embedding-daemon`](packages/embedding-daemon) | Python 3.13 | PyPI: [`mcp-embedding-daemon`](https://pypi.org/project/mcp-embedding-daemon/) | `pip install mcp-embedding-daemon` |
|
|
43
|
+
| [`packages/stdio-proxy`](packages/stdio-proxy) | Python 3.13 | PyPI: [`mcp-stdio-proxy`](https://pypi.org/project/mcp-stdio-proxy/) | `pip install mcp-stdio-proxy` |
|
|
44
|
+
|
|
45
|
+
All four packages share the same version (`semantic-release.toml` bumps all
|
|
46
|
+
three Python `pyproject.toml` files plus the npm `package.json` in lockstep).
|
|
47
|
+
|
|
48
|
+
## What you get
|
|
49
|
+
|
|
50
|
+
### `n24q02m-mcp-core` (Python) and `@n24q02m/mcp-core` (TypeScript)
|
|
51
|
+
|
|
52
|
+
Identical public API in both languages:
|
|
53
|
+
|
|
54
|
+
- **`crypto/`** — ECDH P-256, AES-256-GCM, HKDF-SHA256 primitives.
|
|
55
|
+
Cross-language test vectors guarantee Python and TypeScript produce the
|
|
56
|
+
same ciphertext for the same input.
|
|
57
|
+
- **`storage/`** — encrypted config file (`config.enc`) backed by PBKDF2
|
|
58
|
+
600k + machine-id key derivation, plus session lock files and config
|
|
59
|
+
resolver helpers.
|
|
60
|
+
- **`oauth/`** — OAuth 2.1 Authorization Server building blocks: `JWTIssuer`
|
|
61
|
+
(RS256), `OAuthProvider` (PKCE flow + relay session integration),
|
|
62
|
+
`SqliteUserStore` for multi-user mode.
|
|
63
|
+
- **`relay/`** — `RelaySession`, `create_session`, `poll_for_result`,
|
|
64
|
+
`send_message` plus the EFF Diceware wordlist for passphrase generation.
|
|
65
|
+
- **`schema/`** — `RelayConfigSchema` TypedDict that downstream servers use
|
|
66
|
+
to declare their config form.
|
|
67
|
+
- **`transport/`** — `StreamableHTTPServer` wrapper around FastMCP /
|
|
68
|
+
`@modelcontextprotocol/sdk` Streamable HTTP transport, plus
|
|
69
|
+
`OAuthMiddleware` (RFC 6750 + RFC 9728 compliant Bearer validation).
|
|
70
|
+
- **`lifecycle/`** — `LifecycleLock` cross-platform file lock that prevents
|
|
71
|
+
two server instances from binding the same `(name, port)` pair.
|
|
72
|
+
- **`install/`** (Python only) — `AgentInstaller` that writes MCP server
|
|
73
|
+
entries into Claude Code, Cursor, Codex, Windsurf, and OpenCode config
|
|
74
|
+
files.
|
|
75
|
+
|
|
76
|
+
### `mcp-embedding-daemon`
|
|
77
|
+
|
|
78
|
+
FastAPI HTTP server scaffold for the upcoming shared ONNX/GGUF embedding
|
|
79
|
+
backend. v0.1.0 alpha exposes:
|
|
80
|
+
|
|
81
|
+
- `GET /health` — returns `{status, version}`
|
|
82
|
+
- `POST /embed` — returns 501 with a roadmap link (backend wiring lands in
|
|
83
|
+
the next release)
|
|
84
|
+
- `POST /rerank` — returns 501 with a roadmap link
|
|
85
|
+
|
|
86
|
+
CLI entry point: `mcp-embedding-daemon --host 127.0.0.1 --port 9800`.
|
|
87
|
+
|
|
88
|
+
### `mcp-stdio-proxy`
|
|
89
|
+
|
|
90
|
+
Thin stdio-to-HTTP forwarder for agents that only support stdio MCP transport
|
|
91
|
+
(e.g., Antigravity). Reads JSON-RPC frames from stdin, POSTs them to a remote
|
|
92
|
+
MCP server, writes responses to stdout.
|
|
93
|
+
|
|
94
|
+
CLI entry point: `mcp-stdio-proxy --url https://my-mcp.example.com/mcp --token <bearer>`.
|
|
95
|
+
Falls back to `MCP_CORE_SERVER_URL` and `MCP_CORE_SERVER_TOKEN` env vars when
|
|
96
|
+
flags are not supplied.
|
|
97
|
+
|
|
98
|
+
## Quick start (Python)
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from mcp_core import RelaySession, create_session, decrypt
|
|
102
|
+
from mcp_core.transport.streamable_http import StreamableHTTPServer
|
|
103
|
+
from mcp_core.oauth import JWTIssuer
|
|
104
|
+
from mcp_core.transport.oauth_middleware import OAuthMiddleware
|
|
105
|
+
from fastmcp import FastMCP
|
|
106
|
+
|
|
107
|
+
mcp = FastMCP("my-server")
|
|
108
|
+
|
|
109
|
+
issuer = JWTIssuer("my-server")
|
|
110
|
+
issuer # Use issuer.issue_access_token(sub) / verify_access_token(token)
|
|
111
|
+
|
|
112
|
+
middleware = [OAuthMiddleware(issuer=issuer, resource_metadata_url="http://127.0.0.1:9876/.well-known/oauth-protected-resource")]
|
|
113
|
+
server = StreamableHTTPServer(mcp, port=9876, middleware=middleware)
|
|
114
|
+
server.run()
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Quick start (TypeScript)
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
121
|
+
import { JWTIssuer } from '@n24q02m/mcp-core/oauth'
|
|
122
|
+
import { OAuthMiddleware, StreamableHTTPServer } from '@n24q02m/mcp-core/transport'
|
|
123
|
+
|
|
124
|
+
const server = new McpServer({ name: 'my-server', version: '0.0.0' })
|
|
125
|
+
const issuer = new JWTIssuer('my-server')
|
|
126
|
+
await issuer.init()
|
|
127
|
+
|
|
128
|
+
const middleware = new OAuthMiddleware({
|
|
129
|
+
jwtIssuer: issuer,
|
|
130
|
+
resourceMetadataUrl: 'http://127.0.0.1:9876/.well-known/oauth-protected-resource'
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
const http = new StreamableHTTPServer({ server, port: 9876, oauthMiddleware: middleware })
|
|
134
|
+
await http.connect()
|
|
135
|
+
// Then mount http.handleRequest(req, res) on your http.Server / Express / Hono.
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Development
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
mise run setup # install runtimes + deps + pre-commit hooks
|
|
142
|
+
bun install # root TypeScript workspace install
|
|
143
|
+
|
|
144
|
+
# Python (per package)
|
|
145
|
+
cd packages/core-py
|
|
146
|
+
uv sync --group dev
|
|
147
|
+
uv run pytest
|
|
148
|
+
uv run ty check
|
|
149
|
+
uv run ruff check .
|
|
150
|
+
|
|
151
|
+
# TypeScript
|
|
152
|
+
cd packages/core-ts
|
|
153
|
+
bun run test
|
|
154
|
+
bun run check
|
|
155
|
+
bun run build
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Spec
|
|
159
|
+
|
|
160
|
+
Architecture design lives in
|
|
161
|
+
[claude-plugins/docs/superpowers/specs/2026-04-10-mcp-core-unified-transport-design.md](https://github.com/n24q02m/claude-plugins/blob/feat/phase3-mcp-core-unified/docs/superpowers/specs/2026-04-10-mcp-core-unified-transport-design.md).
|
|
162
|
+
|
|
163
|
+
## License
|
|
164
|
+
|
|
165
|
+
MIT
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# mcp-core
|
|
2
|
+
|
|
3
|
+
Unified MCP Streamable HTTP 2025-11-25 transport, OAuth 2.1 Authorization
|
|
4
|
+
Server, lifecycle management, install automation, and shared embedding
|
|
5
|
+
daemon for the n24q02m MCP ecosystem.
|
|
6
|
+
|
|
7
|
+
`mcp-core` is the **functional successor** to the archived
|
|
8
|
+
[`mcp-relay-core`](https://github.com/n24q02m/mcp-relay-core). All crypto,
|
|
9
|
+
storage, OAuth, relay, and schema modules from `mcp-relay-core` ship under
|
|
10
|
+
the same paths in `mcp-core` (1:1 superset), so downstream MCP servers can
|
|
11
|
+
migrate with a pure import + dependency rename. See
|
|
12
|
+
[`docs/migration-from-mcp-relay-core.md`](docs/migration-from-mcp-relay-core.md)
|
|
13
|
+
for the rename table.
|
|
14
|
+
|
|
15
|
+
## Packages
|
|
16
|
+
|
|
17
|
+
| Package | Language | Registry | Install |
|
|
18
|
+
|---------|----------|----------|---------|
|
|
19
|
+
| [`packages/core-py`](packages/core-py) | Python 3.13 | PyPI: [`n24q02m-mcp-core`](https://pypi.org/project/n24q02m-mcp-core/) | `pip install n24q02m-mcp-core` |
|
|
20
|
+
| [`packages/core-ts`](packages/core-ts) | TypeScript / Node 24 | npm: [`@n24q02m/mcp-core`](https://www.npmjs.com/package/@n24q02m/mcp-core) | `bun add @n24q02m/mcp-core` |
|
|
21
|
+
| [`packages/embedding-daemon`](packages/embedding-daemon) | Python 3.13 | PyPI: [`mcp-embedding-daemon`](https://pypi.org/project/mcp-embedding-daemon/) | `pip install mcp-embedding-daemon` |
|
|
22
|
+
| [`packages/stdio-proxy`](packages/stdio-proxy) | Python 3.13 | PyPI: [`mcp-stdio-proxy`](https://pypi.org/project/mcp-stdio-proxy/) | `pip install mcp-stdio-proxy` |
|
|
23
|
+
|
|
24
|
+
All four packages share the same version (`semantic-release.toml` bumps all
|
|
25
|
+
three Python `pyproject.toml` files plus the npm `package.json` in lockstep).
|
|
26
|
+
|
|
27
|
+
## What you get
|
|
28
|
+
|
|
29
|
+
### `n24q02m-mcp-core` (Python) and `@n24q02m/mcp-core` (TypeScript)
|
|
30
|
+
|
|
31
|
+
Identical public API in both languages:
|
|
32
|
+
|
|
33
|
+
- **`crypto/`** — ECDH P-256, AES-256-GCM, HKDF-SHA256 primitives.
|
|
34
|
+
Cross-language test vectors guarantee Python and TypeScript produce the
|
|
35
|
+
same ciphertext for the same input.
|
|
36
|
+
- **`storage/`** — encrypted config file (`config.enc`) backed by PBKDF2
|
|
37
|
+
600k + machine-id key derivation, plus session lock files and config
|
|
38
|
+
resolver helpers.
|
|
39
|
+
- **`oauth/`** — OAuth 2.1 Authorization Server building blocks: `JWTIssuer`
|
|
40
|
+
(RS256), `OAuthProvider` (PKCE flow + relay session integration),
|
|
41
|
+
`SqliteUserStore` for multi-user mode.
|
|
42
|
+
- **`relay/`** — `RelaySession`, `create_session`, `poll_for_result`,
|
|
43
|
+
`send_message` plus the EFF Diceware wordlist for passphrase generation.
|
|
44
|
+
- **`schema/`** — `RelayConfigSchema` TypedDict that downstream servers use
|
|
45
|
+
to declare their config form.
|
|
46
|
+
- **`transport/`** — `StreamableHTTPServer` wrapper around FastMCP /
|
|
47
|
+
`@modelcontextprotocol/sdk` Streamable HTTP transport, plus
|
|
48
|
+
`OAuthMiddleware` (RFC 6750 + RFC 9728 compliant Bearer validation).
|
|
49
|
+
- **`lifecycle/`** — `LifecycleLock` cross-platform file lock that prevents
|
|
50
|
+
two server instances from binding the same `(name, port)` pair.
|
|
51
|
+
- **`install/`** (Python only) — `AgentInstaller` that writes MCP server
|
|
52
|
+
entries into Claude Code, Cursor, Codex, Windsurf, and OpenCode config
|
|
53
|
+
files.
|
|
54
|
+
|
|
55
|
+
### `mcp-embedding-daemon`
|
|
56
|
+
|
|
57
|
+
FastAPI HTTP server scaffold for the upcoming shared ONNX/GGUF embedding
|
|
58
|
+
backend. v0.1.0 alpha exposes:
|
|
59
|
+
|
|
60
|
+
- `GET /health` — returns `{status, version}`
|
|
61
|
+
- `POST /embed` — returns 501 with a roadmap link (backend wiring lands in
|
|
62
|
+
the next release)
|
|
63
|
+
- `POST /rerank` — returns 501 with a roadmap link
|
|
64
|
+
|
|
65
|
+
CLI entry point: `mcp-embedding-daemon --host 127.0.0.1 --port 9800`.
|
|
66
|
+
|
|
67
|
+
### `mcp-stdio-proxy`
|
|
68
|
+
|
|
69
|
+
Thin stdio-to-HTTP forwarder for agents that only support stdio MCP transport
|
|
70
|
+
(e.g., Antigravity). Reads JSON-RPC frames from stdin, POSTs them to a remote
|
|
71
|
+
MCP server, writes responses to stdout.
|
|
72
|
+
|
|
73
|
+
CLI entry point: `mcp-stdio-proxy --url https://my-mcp.example.com/mcp --token <bearer>`.
|
|
74
|
+
Falls back to `MCP_CORE_SERVER_URL` and `MCP_CORE_SERVER_TOKEN` env vars when
|
|
75
|
+
flags are not supplied.
|
|
76
|
+
|
|
77
|
+
## Quick start (Python)
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from mcp_core import RelaySession, create_session, decrypt
|
|
81
|
+
from mcp_core.transport.streamable_http import StreamableHTTPServer
|
|
82
|
+
from mcp_core.oauth import JWTIssuer
|
|
83
|
+
from mcp_core.transport.oauth_middleware import OAuthMiddleware
|
|
84
|
+
from fastmcp import FastMCP
|
|
85
|
+
|
|
86
|
+
mcp = FastMCP("my-server")
|
|
87
|
+
|
|
88
|
+
issuer = JWTIssuer("my-server")
|
|
89
|
+
issuer # Use issuer.issue_access_token(sub) / verify_access_token(token)
|
|
90
|
+
|
|
91
|
+
middleware = [OAuthMiddleware(issuer=issuer, resource_metadata_url="http://127.0.0.1:9876/.well-known/oauth-protected-resource")]
|
|
92
|
+
server = StreamableHTTPServer(mcp, port=9876, middleware=middleware)
|
|
93
|
+
server.run()
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Quick start (TypeScript)
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
100
|
+
import { JWTIssuer } from '@n24q02m/mcp-core/oauth'
|
|
101
|
+
import { OAuthMiddleware, StreamableHTTPServer } from '@n24q02m/mcp-core/transport'
|
|
102
|
+
|
|
103
|
+
const server = new McpServer({ name: 'my-server', version: '0.0.0' })
|
|
104
|
+
const issuer = new JWTIssuer('my-server')
|
|
105
|
+
await issuer.init()
|
|
106
|
+
|
|
107
|
+
const middleware = new OAuthMiddleware({
|
|
108
|
+
jwtIssuer: issuer,
|
|
109
|
+
resourceMetadataUrl: 'http://127.0.0.1:9876/.well-known/oauth-protected-resource'
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
const http = new StreamableHTTPServer({ server, port: 9876, oauthMiddleware: middleware })
|
|
113
|
+
await http.connect()
|
|
114
|
+
// Then mount http.handleRequest(req, res) on your http.Server / Express / Hono.
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Development
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
mise run setup # install runtimes + deps + pre-commit hooks
|
|
121
|
+
bun install # root TypeScript workspace install
|
|
122
|
+
|
|
123
|
+
# Python (per package)
|
|
124
|
+
cd packages/core-py
|
|
125
|
+
uv sync --group dev
|
|
126
|
+
uv run pytest
|
|
127
|
+
uv run ty check
|
|
128
|
+
uv run ruff check .
|
|
129
|
+
|
|
130
|
+
# TypeScript
|
|
131
|
+
cd packages/core-ts
|
|
132
|
+
bun run test
|
|
133
|
+
bun run check
|
|
134
|
+
bun run build
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Spec
|
|
138
|
+
|
|
139
|
+
Architecture design lives in
|
|
140
|
+
[claude-plugins/docs/superpowers/specs/2026-04-10-mcp-core-unified-transport-design.md](https://github.com/n24q02m/claude-plugins/blob/feat/phase3-mcp-core-unified/docs/superpowers/specs/2026-04-10-mcp-core-unified-transport-design.md).
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
MIT
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "mcp-stdio-proxy"
|
|
7
|
+
version = "1.0.0-beta.3"
|
|
8
|
+
description = "Thin stdio-to-HTTP forwarder for MCP agents lacking HTTP support"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = "==3.13.*"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "n24q02m", email = "quangminh2422004@gmail.com" }]
|
|
13
|
+
keywords = ["mcp", "stdio", "proxy", "transport"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
21
|
+
"Topic :: Software Development :: Libraries",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"httpx>=0.28.1",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Homepage = "https://github.com/n24q02m/mcp-core"
|
|
29
|
+
Repository = "https://github.com/n24q02m/mcp-core"
|
|
30
|
+
Issues = "https://github.com/n24q02m/mcp-core/issues"
|
|
31
|
+
|
|
32
|
+
[project.scripts]
|
|
33
|
+
mcp-stdio-proxy = "mcp_stdio_proxy.main:cli"
|
|
34
|
+
|
|
35
|
+
[dependency-groups]
|
|
36
|
+
dev = [
|
|
37
|
+
"pytest>=9.0.3",
|
|
38
|
+
"pytest-asyncio>=1.2.0",
|
|
39
|
+
"pytest-cov>=7.0.0",
|
|
40
|
+
"ruff>=0.15.7",
|
|
41
|
+
"ty>=0.0.1a22",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[tool.hatch.build.targets.wheel]
|
|
45
|
+
packages = ["src/mcp_stdio_proxy"]
|
|
46
|
+
|
|
47
|
+
[tool.ruff]
|
|
48
|
+
line-length = 120
|
|
49
|
+
target-version = "py313"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Thin stdio to HTTP forwarder.
|
|
2
|
+
|
|
3
|
+
Forwards MCP JSON-RPC frames from stdin to a local HTTP daemon's /mcp
|
|
4
|
+
endpoint and writes responses to stdout. Enables agents that only support
|
|
5
|
+
stdio transport (e.g., Antigravity) to use HTTP-only MCP servers.
|
|
6
|
+
|
|
7
|
+
Spawned by the agent as a stdio MCP server. Reads MCP_CORE_SERVER_URL
|
|
8
|
+
environment variable (or --url CLI flag) to know where to forward.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import asyncio
|
|
15
|
+
import os
|
|
16
|
+
import sys
|
|
17
|
+
|
|
18
|
+
import httpx
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
async def forward(url: str, token: str | None) -> int:
|
|
22
|
+
headers = {"Content-Type": "application/json"}
|
|
23
|
+
if token:
|
|
24
|
+
headers["Authorization"] = f"Bearer {token}"
|
|
25
|
+
|
|
26
|
+
async with httpx.AsyncClient(timeout=None) as client:
|
|
27
|
+
loop = asyncio.get_running_loop()
|
|
28
|
+
reader = asyncio.StreamReader()
|
|
29
|
+
protocol = asyncio.StreamReaderProtocol(reader)
|
|
30
|
+
await loop.connect_read_pipe(lambda: protocol, sys.stdin)
|
|
31
|
+
while True:
|
|
32
|
+
line = await reader.readline()
|
|
33
|
+
if not line:
|
|
34
|
+
return 0
|
|
35
|
+
try:
|
|
36
|
+
resp = await client.post(url, content=line, headers=headers)
|
|
37
|
+
sys.stdout.write(resp.text + "\n")
|
|
38
|
+
sys.stdout.flush()
|
|
39
|
+
except httpx.HTTPError as e:
|
|
40
|
+
sys.stderr.write(f"stdio-proxy HTTP error: {e}\n")
|
|
41
|
+
return 2
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
async def main(url: str | None = None, token: str | None = None) -> int:
|
|
45
|
+
resolved_url = url or os.environ.get("MCP_CORE_SERVER_URL")
|
|
46
|
+
resolved_token = token if token is not None else os.environ.get("MCP_CORE_SERVER_TOKEN")
|
|
47
|
+
if not resolved_url:
|
|
48
|
+
sys.stderr.write("MCP_CORE_SERVER_URL not set. Pass --url <url> or set the env var.\n")
|
|
49
|
+
return 1
|
|
50
|
+
return await forward(resolved_url, resolved_token)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def cli() -> int:
|
|
54
|
+
parser = argparse.ArgumentParser(
|
|
55
|
+
prog="mcp-stdio-proxy",
|
|
56
|
+
description="Forward stdio MCP frames to an HTTP MCP server",
|
|
57
|
+
)
|
|
58
|
+
parser.add_argument(
|
|
59
|
+
"--url",
|
|
60
|
+
default=None,
|
|
61
|
+
help="Upstream HTTP MCP endpoint (default: $MCP_CORE_SERVER_URL)",
|
|
62
|
+
)
|
|
63
|
+
parser.add_argument(
|
|
64
|
+
"--token",
|
|
65
|
+
default=None,
|
|
66
|
+
help="Bearer token (default: $MCP_CORE_SERVER_TOKEN)",
|
|
67
|
+
)
|
|
68
|
+
args = parser.parse_args()
|
|
69
|
+
return asyncio.run(main(url=args.url, token=args.token))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
if __name__ == "__main__":
|
|
73
|
+
sys.exit(cli())
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Tests for mcp_stdio_proxy.main."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import sys
|
|
7
|
+
from io import StringIO
|
|
8
|
+
from unittest.mock import patch
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
from mcp_stdio_proxy.main import main
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_main_returns_1_when_no_url(capsys: pytest.CaptureFixture[str]) -> None:
|
|
16
|
+
with patch.dict("os.environ", {}, clear=True):
|
|
17
|
+
result = asyncio.run(main(url=None, token=None))
|
|
18
|
+
captured = capsys.readouterr()
|
|
19
|
+
assert result == 1
|
|
20
|
+
assert "MCP_CORE_SERVER_URL not set" in captured.err
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_main_uses_env_url_when_no_arg(capsys: pytest.CaptureFixture[str]) -> None:
|
|
24
|
+
# Should pass past the URL check; we redirect stdin to empty so the
|
|
25
|
+
# stdin reader returns EOF immediately and the forwarder exits cleanly.
|
|
26
|
+
sys_stdin = sys.stdin
|
|
27
|
+
try:
|
|
28
|
+
sys.stdin = StringIO("")
|
|
29
|
+
with patch.dict(
|
|
30
|
+
"os.environ",
|
|
31
|
+
{"MCP_CORE_SERVER_URL": "http://127.0.0.1:0/mcp"},
|
|
32
|
+
clear=True,
|
|
33
|
+
):
|
|
34
|
+
# We don't actually run the forwarder loop here because connecting
|
|
35
|
+
# to a fake stdin in pytest is unreliable across platforms; instead
|
|
36
|
+
# we just confirm the URL resolution path doesn't raise on entry.
|
|
37
|
+
from mcp_stdio_proxy.main import forward
|
|
38
|
+
|
|
39
|
+
assert callable(forward)
|
|
40
|
+
assert forward.__name__ == "forward"
|
|
41
|
+
finally:
|
|
42
|
+
sys.stdin = sys_stdin
|
|
43
|
+
captured = capsys.readouterr()
|
|
44
|
+
assert "MCP_CORE_SERVER_URL not set" not in captured.err
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_cli_resolves_url_from_argument(capsys: pytest.CaptureFixture[str]) -> None:
|
|
48
|
+
# Patching argv lets cli() parse the --url flag without env vars.
|
|
49
|
+
with (
|
|
50
|
+
patch.object(sys, "argv", ["mcp-stdio-proxy", "--url", ""]),
|
|
51
|
+
patch.dict("os.environ", {}, clear=True),
|
|
52
|
+
):
|
|
53
|
+
from mcp_stdio_proxy.main import main as main_fn
|
|
54
|
+
|
|
55
|
+
# Empty --url falls through to env var (also empty), so it should still
|
|
56
|
+
# report missing URL. This validates that argparse doesn't crash on
|
|
57
|
+
# the flag and that empty string is treated like missing.
|
|
58
|
+
result = asyncio.run(main_fn(url="", token=None))
|
|
59
|
+
captured = capsys.readouterr()
|
|
60
|
+
assert result == 1
|
|
61
|
+
assert "MCP_CORE_SERVER_URL not set" in captured.err
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 3
|
|
3
|
+
requires-python = "==3.13.*"
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "anyio"
|
|
7
|
+
version = "4.13.0"
|
|
8
|
+
source = { registry = "https://pypi.org/simple" }
|
|
9
|
+
dependencies = [
|
|
10
|
+
{ name = "idna" },
|
|
11
|
+
]
|
|
12
|
+
sdist = { url = "https://files.pythonhosted.org/packages/19/14/2c5dd9f512b66549ae92767a9c7b330ae88e1932ca57876909410251fe13/anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc", size = 231622, upload-time = "2026-03-24T12:59:09.671Z" }
|
|
13
|
+
wheels = [
|
|
14
|
+
{ url = "https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708", size = 114353, upload-time = "2026-03-24T12:59:08.246Z" },
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "certifi"
|
|
19
|
+
version = "2026.2.25"
|
|
20
|
+
source = { registry = "https://pypi.org/simple" }
|
|
21
|
+
sdist = { url = "https://files.pythonhosted.org/packages/af/2d/7bf41579a8986e348fa033a31cdd0e4121114f6bce2457e8876010b092dd/certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7", size = 155029, upload-time = "2026-02-25T02:54:17.342Z" }
|
|
22
|
+
wheels = [
|
|
23
|
+
{ url = "https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", size = 153684, upload-time = "2026-02-25T02:54:15.766Z" },
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[[package]]
|
|
27
|
+
name = "colorama"
|
|
28
|
+
version = "0.4.6"
|
|
29
|
+
source = { registry = "https://pypi.org/simple" }
|
|
30
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
|
31
|
+
wheels = [
|
|
32
|
+
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[[package]]
|
|
36
|
+
name = "coverage"
|
|
37
|
+
version = "7.13.5"
|
|
38
|
+
source = { registry = "https://pypi.org/simple" }
|
|
39
|
+
sdist = { url = "https://files.pythonhosted.org/packages/9d/e0/70553e3000e345daff267cec284ce4cbf3fc141b6da229ac52775b5428f1/coverage-7.13.5.tar.gz", hash = "sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179", size = 915967, upload-time = "2026-03-17T10:33:18.341Z" }
|
|
40
|
+
wheels = [
|
|
41
|
+
{ url = "https://files.pythonhosted.org/packages/74/8c/74fedc9663dcf168b0a059d4ea756ecae4da77a489048f94b5f512a8d0b3/coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1", size = 219576, upload-time = "2026-03-17T10:31:09.045Z" },
|
|
42
|
+
{ url = "https://files.pythonhosted.org/packages/0c/c9/44fb661c55062f0818a6ffd2685c67aa30816200d5f2817543717d4b92eb/coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3", size = 219942, upload-time = "2026-03-17T10:31:10.708Z" },
|
|
43
|
+
{ url = "https://files.pythonhosted.org/packages/5f/13/93419671cee82b780bab7ea96b67c8ef448f5f295f36bf5031154ec9a790/coverage-7.13.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26", size = 250935, upload-time = "2026-03-17T10:31:12.392Z" },
|
|
44
|
+
{ url = "https://files.pythonhosted.org/packages/ac/68/1666e3a4462f8202d836920114fa7a5ee9275d1fa45366d336c551a162dd/coverage-7.13.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3", size = 253541, upload-time = "2026-03-17T10:31:14.247Z" },
|
|
45
|
+
{ url = "https://files.pythonhosted.org/packages/4e/5e/3ee3b835647be646dcf3c65a7c6c18f87c27326a858f72ab22c12730773d/coverage-7.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b", size = 254780, upload-time = "2026-03-17T10:31:16.193Z" },
|
|
46
|
+
{ url = "https://files.pythonhosted.org/packages/44/b3/cb5bd1a04cfcc49ede6cd8409d80bee17661167686741e041abc7ee1b9a9/coverage-7.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a", size = 256912, upload-time = "2026-03-17T10:31:17.89Z" },
|
|
47
|
+
{ url = "https://files.pythonhosted.org/packages/1b/66/c1dceb7b9714473800b075f5c8a84f4588f887a90eb8645282031676e242/coverage-7.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969", size = 251165, upload-time = "2026-03-17T10:31:19.605Z" },
|
|
48
|
+
{ url = "https://files.pythonhosted.org/packages/b7/62/5502b73b97aa2e53ea22a39cf8649ff44827bef76d90bf638777daa27a9d/coverage-7.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161", size = 252908, upload-time = "2026-03-17T10:31:21.312Z" },
|
|
49
|
+
{ url = "https://files.pythonhosted.org/packages/7d/37/7792c2d69854397ca77a55c4646e5897c467928b0e27f2d235d83b5d08c6/coverage-7.13.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15", size = 250873, upload-time = "2026-03-17T10:31:23.565Z" },
|
|
50
|
+
{ url = "https://files.pythonhosted.org/packages/a3/23/bc866fb6163be52a8a9e5d708ba0d3b1283c12158cefca0a8bbb6e247a43/coverage-7.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1", size = 255030, upload-time = "2026-03-17T10:31:25.58Z" },
|
|
51
|
+
{ url = "https://files.pythonhosted.org/packages/7d/8b/ef67e1c222ef49860701d346b8bbb70881bef283bd5f6cbba68a39a086c7/coverage-7.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6", size = 250694, upload-time = "2026-03-17T10:31:27.316Z" },
|
|
52
|
+
{ url = "https://files.pythonhosted.org/packages/46/0d/866d1f74f0acddbb906db212e096dee77a8e2158ca5e6bb44729f9d93298/coverage-7.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17", size = 252469, upload-time = "2026-03-17T10:31:29.472Z" },
|
|
53
|
+
{ url = "https://files.pythonhosted.org/packages/7a/f5/be742fec31118f02ce42b21c6af187ad6a344fed546b56ca60caacc6a9a0/coverage-7.13.5-cp313-cp313-win32.whl", hash = "sha256:ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85", size = 222112, upload-time = "2026-03-17T10:31:31.526Z" },
|
|
54
|
+
{ url = "https://files.pythonhosted.org/packages/66/40/7732d648ab9d069a46e686043241f01206348e2bbf128daea85be4d6414b/coverage-7.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b", size = 222923, upload-time = "2026-03-17T10:31:33.633Z" },
|
|
55
|
+
{ url = "https://files.pythonhosted.org/packages/48/af/fea819c12a095781f6ccd504890aaddaf88b8fab263c4940e82c7b770124/coverage-7.13.5-cp313-cp313-win_arm64.whl", hash = "sha256:f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664", size = 221540, upload-time = "2026-03-17T10:31:35.445Z" },
|
|
56
|
+
{ url = "https://files.pythonhosted.org/packages/23/d2/17879af479df7fbbd44bd528a31692a48f6b25055d16482fdf5cdb633805/coverage-7.13.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d", size = 220262, upload-time = "2026-03-17T10:31:37.184Z" },
|
|
57
|
+
{ url = "https://files.pythonhosted.org/packages/5b/4c/d20e554f988c8f91d6a02c5118f9abbbf73a8768a3048cb4962230d5743f/coverage-7.13.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0", size = 220617, upload-time = "2026-03-17T10:31:39.245Z" },
|
|
58
|
+
{ url = "https://files.pythonhosted.org/packages/29/9c/f9f5277b95184f764b24e7231e166dfdb5780a46d408a2ac665969416d61/coverage-7.13.5-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806", size = 261912, upload-time = "2026-03-17T10:31:41.324Z" },
|
|
59
|
+
{ url = "https://files.pythonhosted.org/packages/d5/f6/7f1ab39393eeb50cfe4747ae8ef0e4fc564b989225aa1152e13a180d74f8/coverage-7.13.5-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3", size = 263987, upload-time = "2026-03-17T10:31:43.724Z" },
|
|
60
|
+
{ url = "https://files.pythonhosted.org/packages/a0/d7/62c084fb489ed9c6fbdf57e006752e7c516ea46fd690e5ed8b8617c7d52e/coverage-7.13.5-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9", size = 266416, upload-time = "2026-03-17T10:31:45.769Z" },
|
|
61
|
+
{ url = "https://files.pythonhosted.org/packages/a9/f6/df63d8660e1a0bff6125947afda112a0502736f470d62ca68b288ea762d8/coverage-7.13.5-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd", size = 267558, upload-time = "2026-03-17T10:31:48.293Z" },
|
|
62
|
+
{ url = "https://files.pythonhosted.org/packages/5b/02/353ca81d36779bd108f6d384425f7139ac3c58c750dcfaafe5d0bee6436b/coverage-7.13.5-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606", size = 261163, upload-time = "2026-03-17T10:31:50.125Z" },
|
|
63
|
+
{ url = "https://files.pythonhosted.org/packages/2c/16/2e79106d5749bcaf3aee6d309123548e3276517cd7851faa8da213bc61bf/coverage-7.13.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e", size = 263981, upload-time = "2026-03-17T10:31:51.961Z" },
|
|
64
|
+
{ url = "https://files.pythonhosted.org/packages/29/c7/c29e0c59ffa6942030ae6f50b88ae49988e7e8da06de7ecdbf49c6d4feae/coverage-7.13.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0", size = 261604, upload-time = "2026-03-17T10:31:53.872Z" },
|
|
65
|
+
{ url = "https://files.pythonhosted.org/packages/40/48/097cdc3db342f34006a308ab41c3a7c11c3f0d84750d340f45d88a782e00/coverage-7.13.5-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87", size = 265321, upload-time = "2026-03-17T10:31:55.997Z" },
|
|
66
|
+
{ url = "https://files.pythonhosted.org/packages/bb/1f/4994af354689e14fd03a75f8ec85a9a68d94e0188bbdab3fc1516b55e512/coverage-7.13.5-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479", size = 260502, upload-time = "2026-03-17T10:31:58.308Z" },
|
|
67
|
+
{ url = "https://files.pythonhosted.org/packages/22/c6/9bb9ef55903e628033560885f5c31aa227e46878118b63ab15dc7ba87797/coverage-7.13.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2", size = 262688, upload-time = "2026-03-17T10:32:00.141Z" },
|
|
68
|
+
{ url = "https://files.pythonhosted.org/packages/14/4f/f5df9007e50b15e53e01edea486814783a7f019893733d9e4d6caad75557/coverage-7.13.5-cp313-cp313t-win32.whl", hash = "sha256:67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a", size = 222788, upload-time = "2026-03-17T10:32:02.246Z" },
|
|
69
|
+
{ url = "https://files.pythonhosted.org/packages/e1/98/aa7fccaa97d0f3192bec013c4e6fd6d294a6ed44b640e6bb61f479e00ed5/coverage-7.13.5-cp313-cp313t-win_amd64.whl", hash = "sha256:da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819", size = 223851, upload-time = "2026-03-17T10:32:04.416Z" },
|
|
70
|
+
{ url = "https://files.pythonhosted.org/packages/3d/8b/e5c469f7352651e5f013198e9e21f97510b23de957dd06a84071683b4b60/coverage-7.13.5-cp313-cp313t-win_arm64.whl", hash = "sha256:0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911", size = 222104, upload-time = "2026-03-17T10:32:06.65Z" },
|
|
71
|
+
{ url = "https://files.pythonhosted.org/packages/9e/ee/a4cf96b8ce1e566ed238f0659ac2d3f007ed1d14b181bcb684e19561a69a/coverage-7.13.5-py3-none-any.whl", hash = "sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61", size = 211346, upload-time = "2026-03-17T10:33:15.691Z" },
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
[[package]]
|
|
75
|
+
name = "h11"
|
|
76
|
+
version = "0.16.0"
|
|
77
|
+
source = { registry = "https://pypi.org/simple" }
|
|
78
|
+
sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
|
|
79
|
+
wheels = [
|
|
80
|
+
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
[[package]]
|
|
84
|
+
name = "httpcore"
|
|
85
|
+
version = "1.0.9"
|
|
86
|
+
source = { registry = "https://pypi.org/simple" }
|
|
87
|
+
dependencies = [
|
|
88
|
+
{ name = "certifi" },
|
|
89
|
+
{ name = "h11" },
|
|
90
|
+
]
|
|
91
|
+
sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
|
|
92
|
+
wheels = [
|
|
93
|
+
{ url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
[[package]]
|
|
97
|
+
name = "httpx"
|
|
98
|
+
version = "0.28.1"
|
|
99
|
+
source = { registry = "https://pypi.org/simple" }
|
|
100
|
+
dependencies = [
|
|
101
|
+
{ name = "anyio" },
|
|
102
|
+
{ name = "certifi" },
|
|
103
|
+
{ name = "httpcore" },
|
|
104
|
+
{ name = "idna" },
|
|
105
|
+
]
|
|
106
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
|
|
107
|
+
wheels = [
|
|
108
|
+
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
[[package]]
|
|
112
|
+
name = "idna"
|
|
113
|
+
version = "3.11"
|
|
114
|
+
source = { registry = "https://pypi.org/simple" }
|
|
115
|
+
sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" }
|
|
116
|
+
wheels = [
|
|
117
|
+
{ url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" },
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
[[package]]
|
|
121
|
+
name = "iniconfig"
|
|
122
|
+
version = "2.3.0"
|
|
123
|
+
source = { registry = "https://pypi.org/simple" }
|
|
124
|
+
sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
|
|
125
|
+
wheels = [
|
|
126
|
+
{ url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
[[package]]
|
|
130
|
+
name = "mcp-stdio-proxy"
|
|
131
|
+
version = "0.1.0"
|
|
132
|
+
source = { editable = "." }
|
|
133
|
+
dependencies = [
|
|
134
|
+
{ name = "httpx" },
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
[package.dev-dependencies]
|
|
138
|
+
dev = [
|
|
139
|
+
{ name = "pytest" },
|
|
140
|
+
{ name = "pytest-asyncio" },
|
|
141
|
+
{ name = "pytest-cov" },
|
|
142
|
+
{ name = "ruff" },
|
|
143
|
+
{ name = "ty" },
|
|
144
|
+
]
|
|
145
|
+
|
|
146
|
+
[package.metadata]
|
|
147
|
+
requires-dist = [{ name = "httpx", specifier = ">=0.28.1" }]
|
|
148
|
+
|
|
149
|
+
[package.metadata.requires-dev]
|
|
150
|
+
dev = [
|
|
151
|
+
{ name = "pytest", specifier = ">=9.0.3" },
|
|
152
|
+
{ name = "pytest-asyncio", specifier = ">=1.2.0" },
|
|
153
|
+
{ name = "pytest-cov", specifier = ">=7.0.0" },
|
|
154
|
+
{ name = "ruff", specifier = ">=0.15.7" },
|
|
155
|
+
{ name = "ty", specifier = ">=0.0.1a22" },
|
|
156
|
+
]
|
|
157
|
+
|
|
158
|
+
[[package]]
|
|
159
|
+
name = "packaging"
|
|
160
|
+
version = "26.0"
|
|
161
|
+
source = { registry = "https://pypi.org/simple" }
|
|
162
|
+
sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" }
|
|
163
|
+
wheels = [
|
|
164
|
+
{ url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" },
|
|
165
|
+
]
|
|
166
|
+
|
|
167
|
+
[[package]]
|
|
168
|
+
name = "pluggy"
|
|
169
|
+
version = "1.6.0"
|
|
170
|
+
source = { registry = "https://pypi.org/simple" }
|
|
171
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
|
|
172
|
+
wheels = [
|
|
173
|
+
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
|
174
|
+
]
|
|
175
|
+
|
|
176
|
+
[[package]]
|
|
177
|
+
name = "pygments"
|
|
178
|
+
version = "2.20.0"
|
|
179
|
+
source = { registry = "https://pypi.org/simple" }
|
|
180
|
+
sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
|
|
181
|
+
wheels = [
|
|
182
|
+
{ url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
[[package]]
|
|
186
|
+
name = "pytest"
|
|
187
|
+
version = "9.0.3"
|
|
188
|
+
source = { registry = "https://pypi.org/simple" }
|
|
189
|
+
dependencies = [
|
|
190
|
+
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
|
191
|
+
{ name = "iniconfig" },
|
|
192
|
+
{ name = "packaging" },
|
|
193
|
+
{ name = "pluggy" },
|
|
194
|
+
{ name = "pygments" },
|
|
195
|
+
]
|
|
196
|
+
sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" }
|
|
197
|
+
wheels = [
|
|
198
|
+
{ url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" },
|
|
199
|
+
]
|
|
200
|
+
|
|
201
|
+
[[package]]
|
|
202
|
+
name = "pytest-asyncio"
|
|
203
|
+
version = "1.3.0"
|
|
204
|
+
source = { registry = "https://pypi.org/simple" }
|
|
205
|
+
dependencies = [
|
|
206
|
+
{ name = "pytest" },
|
|
207
|
+
]
|
|
208
|
+
sdist = { url = "https://files.pythonhosted.org/packages/90/2c/8af215c0f776415f3590cac4f9086ccefd6fd463befeae41cd4d3f193e5a/pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5", size = 50087, upload-time = "2025-11-10T16:07:47.256Z" }
|
|
209
|
+
wheels = [
|
|
210
|
+
{ url = "https://files.pythonhosted.org/packages/e5/35/f8b19922b6a25bc0880171a2f1a003eaeb93657475193ab516fd87cac9da/pytest_asyncio-1.3.0-py3-none-any.whl", hash = "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5", size = 15075, upload-time = "2025-11-10T16:07:45.537Z" },
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
[[package]]
|
|
214
|
+
name = "pytest-cov"
|
|
215
|
+
version = "7.1.0"
|
|
216
|
+
source = { registry = "https://pypi.org/simple" }
|
|
217
|
+
dependencies = [
|
|
218
|
+
{ name = "coverage" },
|
|
219
|
+
{ name = "pluggy" },
|
|
220
|
+
{ name = "pytest" },
|
|
221
|
+
]
|
|
222
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592, upload-time = "2026-03-21T20:11:16.284Z" }
|
|
223
|
+
wheels = [
|
|
224
|
+
{ url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z" },
|
|
225
|
+
]
|
|
226
|
+
|
|
227
|
+
[[package]]
|
|
228
|
+
name = "ruff"
|
|
229
|
+
version = "0.15.10"
|
|
230
|
+
source = { registry = "https://pypi.org/simple" }
|
|
231
|
+
sdist = { url = "https://files.pythonhosted.org/packages/e7/d9/aa3f7d59a10ef6b14fe3431706f854dbf03c5976be614a9796d36326810c/ruff-0.15.10.tar.gz", hash = "sha256:d1f86e67ebfdef88e00faefa1552b5e510e1d35f3be7d423dc7e84e63788c94e", size = 4631728, upload-time = "2026-04-09T14:06:09.884Z" }
|
|
232
|
+
wheels = [
|
|
233
|
+
{ url = "https://files.pythonhosted.org/packages/eb/00/a1c2fdc9939b2c03691edbda290afcd297f1f389196172826b03d6b6a595/ruff-0.15.10-py3-none-linux_armv6l.whl", hash = "sha256:0744e31482f8f7d0d10a11fcbf897af272fefdfcb10f5af907b18c2813ff4d5f", size = 10563362, upload-time = "2026-04-09T14:06:21.189Z" },
|
|
234
|
+
{ url = "https://files.pythonhosted.org/packages/5c/15/006990029aea0bebe9d33c73c3e28c80c391ebdba408d1b08496f00d422d/ruff-0.15.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b1e7c16ea0ff5a53b7c2df52d947e685973049be1cdfe2b59a9c43601897b22e", size = 10951122, upload-time = "2026-04-09T14:06:02.236Z" },
|
|
235
|
+
{ url = "https://files.pythonhosted.org/packages/f2/c0/4ac978fe874d0618c7da647862afe697b281c2806f13ce904ad652fa87e4/ruff-0.15.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:93cc06a19e5155b4441dd72808fdf84290d84ad8a39ca3b0f994363ade4cebb1", size = 10314005, upload-time = "2026-04-09T14:06:00.026Z" },
|
|
236
|
+
{ url = "https://files.pythonhosted.org/packages/da/73/c209138a5c98c0d321266372fc4e33ad43d506d7e5dd817dd89b60a8548f/ruff-0.15.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83e1dd04312997c99ea6965df66a14fb4f03ba978564574ffc68b0d61fd3989e", size = 10643450, upload-time = "2026-04-09T14:05:42.137Z" },
|
|
237
|
+
{ url = "https://files.pythonhosted.org/packages/ec/76/0deec355d8ec10709653635b1f90856735302cb8e149acfdf6f82a5feb70/ruff-0.15.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8154d43684e4333360fedd11aaa40b1b08a4e37d8ffa9d95fee6fa5b37b6fab1", size = 10379597, upload-time = "2026-04-09T14:05:49.984Z" },
|
|
238
|
+
{ url = "https://files.pythonhosted.org/packages/dc/be/86bba8fc8798c081e28a4b3bb6d143ccad3fd5f6f024f02002b8f08a9fa3/ruff-0.15.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ab88715f3a6deb6bde6c227f3a123410bec7b855c3ae331b4c006189e895cef", size = 11146645, upload-time = "2026-04-09T14:06:12.246Z" },
|
|
239
|
+
{ url = "https://files.pythonhosted.org/packages/a8/89/140025e65911b281c57be1d385ba1d932c2366ca88ae6663685aed8d4881/ruff-0.15.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a768ff5969b4f44c349d48edf4ab4f91eddb27fd9d77799598e130fb628aa158", size = 12030289, upload-time = "2026-04-09T14:06:04.776Z" },
|
|
240
|
+
{ url = "https://files.pythonhosted.org/packages/88/de/ddacca9545a5e01332567db01d44bd8cf725f2db3b3d61a80550b48308ea/ruff-0.15.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ee3ef42dab7078bda5ff6a1bcba8539e9857deb447132ad5566a038674540d0", size = 11496266, upload-time = "2026-04-09T14:05:55.485Z" },
|
|
241
|
+
{ url = "https://files.pythonhosted.org/packages/bc/bb/7ddb00a83760ff4a83c4e2fc231fd63937cc7317c10c82f583302e0f6586/ruff-0.15.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51cb8cc943e891ba99989dd92d61e29b1d231e14811db9be6440ecf25d5c1609", size = 11256418, upload-time = "2026-04-09T14:05:57.69Z" },
|
|
242
|
+
{ url = "https://files.pythonhosted.org/packages/dc/8d/55de0d35aacf6cd50b6ee91ee0f291672080021896543776f4170fc5c454/ruff-0.15.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:e59c9bdc056a320fb9ea1700a8d591718b8faf78af065484e801258d3a76bc3f", size = 11288416, upload-time = "2026-04-09T14:05:44.695Z" },
|
|
243
|
+
{ url = "https://files.pythonhosted.org/packages/68/cf/9438b1a27426ec46a80e0a718093c7f958ef72f43eb3111862949ead3cc1/ruff-0.15.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:136c00ca2f47b0018b073f28cb5c1506642a830ea941a60354b0e8bc8076b151", size = 10621053, upload-time = "2026-04-09T14:05:52.782Z" },
|
|
244
|
+
{ url = "https://files.pythonhosted.org/packages/4c/50/e29be6e2c135e9cd4cb15fbade49d6a2717e009dff3766dd080fcb82e251/ruff-0.15.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8b80a2f3c9c8a950d6237f2ca12b206bccff626139be9fa005f14feb881a1ae8", size = 10378302, upload-time = "2026-04-09T14:06:14.361Z" },
|
|
245
|
+
{ url = "https://files.pythonhosted.org/packages/18/2f/e0b36a6f99c51bb89f3a30239bc7bf97e87a37ae80aa2d6542d6e5150364/ruff-0.15.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e3e53c588164dc025b671c9df2462429d60357ea91af7e92e9d56c565a9f1b07", size = 10850074, upload-time = "2026-04-09T14:06:16.581Z" },
|
|
246
|
+
{ url = "https://files.pythonhosted.org/packages/11/08/874da392558ce087a0f9b709dc6ec0d60cbc694c1c772dab8d5f31efe8cb/ruff-0.15.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b0c52744cf9f143a393e284125d2576140b68264a93c6716464e129a3e9adb48", size = 11358051, upload-time = "2026-04-09T14:06:18.948Z" },
|
|
247
|
+
{ url = "https://files.pythonhosted.org/packages/e4/46/602938f030adfa043e67112b73821024dc79f3ab4df5474c25fa4c1d2d14/ruff-0.15.10-py3-none-win32.whl", hash = "sha256:d4272e87e801e9a27a2e8df7b21011c909d9ddd82f4f3281d269b6ba19789ca5", size = 10588964, upload-time = "2026-04-09T14:06:07.14Z" },
|
|
248
|
+
{ url = "https://files.pythonhosted.org/packages/25/b6/261225b875d7a13b33a6d02508c39c28450b2041bb01d0f7f1a83d569512/ruff-0.15.10-py3-none-win_amd64.whl", hash = "sha256:28cb32d53203242d403d819fd6983152489b12e4a3ae44993543d6fe62ab42ed", size = 11745044, upload-time = "2026-04-09T14:05:39.473Z" },
|
|
249
|
+
{ url = "https://files.pythonhosted.org/packages/58/ed/dea90a65b7d9e69888890fb14c90d7f51bf0c1e82ad800aeb0160e4bacfd/ruff-0.15.10-py3-none-win_arm64.whl", hash = "sha256:601d1610a9e1f1c2165a4f561eeaa2e2ea1e97f3287c5aa258d3dab8b57c6188", size = 11035607, upload-time = "2026-04-09T14:05:47.593Z" },
|
|
250
|
+
]
|
|
251
|
+
|
|
252
|
+
[[package]]
|
|
253
|
+
name = "ty"
|
|
254
|
+
version = "0.0.29"
|
|
255
|
+
source = { registry = "https://pypi.org/simple" }
|
|
256
|
+
sdist = { url = "https://files.pythonhosted.org/packages/47/d5/853561de49fae38c519e905b2d8da9c531219608f1fccc47a0fc2c896980/ty-0.0.29.tar.gz", hash = "sha256:e7936cca2f691eeda631876c92809688dbbab68687c3473f526cd83b6a9228d8", size = 5469221, upload-time = "2026-04-05T15:01:21.328Z" }
|
|
257
|
+
wheels = [
|
|
258
|
+
{ url = "https://files.pythonhosted.org/packages/03/b7/911f9962115acfa24e3b2ec9d4992dd994c38e8769e1b1d7680bb4d28a51/ty-0.0.29-py3-none-linux_armv6l.whl", hash = "sha256:b8a40955f7660d3eaceb0d964affc81b790c0765e7052921a5f861ff8a471c30", size = 10568206, upload-time = "2026-04-05T15:01:19.165Z" },
|
|
259
|
+
{ url = "https://files.pythonhosted.org/packages/fe/c3/fcae2167d4c77a97269f92f11d1b43b03617f81de1283d5d05b43432110c/ty-0.0.29-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6b6849adae15b00bbe2d3c5b078967dcb62eba37d38936b8eeb4c81a82d2e3b8", size = 10442530, upload-time = "2026-04-05T15:01:28.471Z" },
|
|
260
|
+
{ url = "https://files.pythonhosted.org/packages/97/33/5a6bfa240cfcb9c36046ae2459fa9ea23238d20130d8656ff5ac4d6c012a/ty-0.0.29-py3-none-macosx_11_0_arm64.whl", hash = "sha256:dcdd9b17209788152f7b7ea815eda07989152325052fe690013537cc7904ce49", size = 9915735, upload-time = "2026-04-05T15:01:10.365Z" },
|
|
261
|
+
{ url = "https://files.pythonhosted.org/packages/b3/1e/318f45fae232118e81a6306c30f50de42c509c412128d5bd231eab699ffb/ty-0.0.29-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d8ed4789bae78ffaf94462c0d25589a734cab0366b86f2bbcb1bb90e1a7a169", size = 10419748, upload-time = "2026-04-05T15:01:32.375Z" },
|
|
262
|
+
{ url = "https://files.pythonhosted.org/packages/a9/a8/5687872e2ab5a0f7dd4fd8456eac31e9381ad4dc74961f6f29965ad4dd91/ty-0.0.29-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91ec374b8565e0ad0900011c24641ebbef2da51adbd4fb69ff3280c8a7eceb02", size = 10394738, upload-time = "2026-04-05T15:01:06.473Z" },
|
|
263
|
+
{ url = "https://files.pythonhosted.org/packages/de/68/015d118097eeb95e6a44c4abce4c0a28b7b9dfb3085b7f0ee48e4f099633/ty-0.0.29-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:298a8d5faa2502d3810bbbb47a030b9455495b9921594206043c785dd61548cf", size = 10910613, upload-time = "2026-04-05T15:01:17.17Z" },
|
|
264
|
+
{ url = "https://files.pythonhosted.org/packages/1c/01/47ce3c6c53e0670eadbe80756b167bf80ed6681d1ba57cfde2e8065a13d1/ty-0.0.29-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c8fba1a3524c6109d1e020d92301c79d41bf442fa8d335b9fa366239339cb70", size = 11475750, upload-time = "2026-04-05T15:01:30.461Z" },
|
|
265
|
+
{ url = "https://files.pythonhosted.org/packages/c4/cf/e361845b1081c9264ad5b7c963231bab03f2666865a9f2a115c4233f2137/ty-0.0.29-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c48adf88a70d264128c39ee922ed14a947817fced1e93c08c1a89c9244edcde", size = 11190055, upload-time = "2026-04-05T15:01:12.369Z" },
|
|
266
|
+
{ url = "https://files.pythonhosted.org/packages/79/12/0fb0857e9a62cb11586e9a712103877bbf717f5fb570d16634408cfdefee/ty-0.0.29-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ce0a7a0e96bc7b42518cd3a1a6a6298ef64ff40ca4614355c1aa807059b5c6f", size = 11020539, upload-time = "2026-04-05T15:01:37.022Z" },
|
|
267
|
+
{ url = "https://files.pythonhosted.org/packages/20/36/5a26753802083f80cd125db6c4348ad42b3c982ec36e718e0bf4c18f75e5/ty-0.0.29-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a6ac86a05b4a3731d45365ab97780acc7b8146fa62fccb3cbe94fe6546c67a97", size = 10396399, upload-time = "2026-04-05T15:01:26.167Z" },
|
|
268
|
+
{ url = "https://files.pythonhosted.org/packages/00/e6/b4e75b5752239ab3ab400f19faef4dbef81d05aab5d3419fda0c062a3765/ty-0.0.29-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6bbbf53141af0f3150bf288d716263f1a3550054e4b3551ca866d38192ba9891", size = 10421461, upload-time = "2026-04-05T15:01:08.367Z" },
|
|
269
|
+
{ url = "https://files.pythonhosted.org/packages/c0/21/1084b5b609f9abed62070ec0b31c283a403832a6310c8bbc208bd45ee1e6/ty-0.0.29-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1c9e06b770c1d0ff5efc51e34312390db31d53fcf3088163f413030b42b74f84", size = 10599187, upload-time = "2026-04-05T15:01:23.52Z" },
|
|
270
|
+
{ url = "https://files.pythonhosted.org/packages/ab/a1/ce19a2ca717bbcc1ee11378aba52ef70b6ce5b87245162a729d9fdc2360f/ty-0.0.29-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0307fe37e3f000ef1a4ae230bbaf511508a78d24a5e51b40902a21b09d5e6037", size = 11121198, upload-time = "2026-04-05T15:01:15.22Z" },
|
|
271
|
+
{ url = "https://files.pythonhosted.org/packages/6b/6b/f1430b279af704321566ce7ec2725d3d8258c2f815ebd93e474c64cd4543/ty-0.0.29-py3-none-win32.whl", hash = "sha256:7a2a898217960a825f8bc0087e1fdbaf379606175e98f9807187221d53a4a8ed", size = 9995331, upload-time = "2026-04-05T15:01:01.32Z" },
|
|
272
|
+
{ url = "https://files.pythonhosted.org/packages/d2/ef/3ef01c17785ff9a69378465c7d0faccd48a07b163554db0995e5d65a5a23/ty-0.0.29-py3-none-win_amd64.whl", hash = "sha256:fc1294200226b91615acbf34e0a9ad81caf98c081e9c6a912a31b0a7b603bc3f", size = 11023644, upload-time = "2026-04-05T15:01:04.432Z" },
|
|
273
|
+
{ url = "https://files.pythonhosted.org/packages/2c/55/87280a994d6a2d2647c65e12abbc997ed49835794366153c04c4d9304d76/ty-0.0.29-py3-none-win_arm64.whl", hash = "sha256:f9794bbd1bb3ce13f78c191d0c89ae4c63f52c12b6daa0c6fe220b90d019d12c", size = 10428165, upload-time = "2026-04-05T15:01:34.665Z" },
|
|
274
|
+
]
|