aiohttp-tiny-mcp 0.4.0__tar.gz → 0.4.1__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.
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/PKG-INFO +4 -4
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/README.md +3 -3
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/pyproject.toml +1 -1
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/pyproject.toml.orig +1 -1
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/console/__init__.py +21 -1
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/console/console.css +9 -2
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/console/console.js +420 -18
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/console/index.html +36 -1
- aiohttp_tiny_mcp-0.4.1/src/aiohttp_tiny_mcp/console/oauth-callback.html +14 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/endpoint.py +7 -4
- aiohttp_tiny_mcp-0.4.1/src/aiohttp_tiny_mcp/metadata.py +44 -0
- aiohttp_tiny_mcp-0.4.1/src/aiohttp_tiny_mcp/oauth/__init__.py +15 -0
- aiohttp_tiny_mcp-0.4.1/src/aiohttp_tiny_mcp/oauth/facade.py +551 -0
- aiohttp_tiny_mcp-0.4.1/src/aiohttp_tiny_mcp/oauth/github.py +45 -0
- aiohttp_tiny_mcp-0.4.1/src/aiohttp_tiny_mcp/oauth/upstream.py +117 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/LICENSE +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/__init__.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/adapter.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/auth.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/client.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/client_base.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/core.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/dispatcher.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/exchange.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/extensions.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/http_sse.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/hub.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/models.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/namespaces.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/postgres.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/protocol/__init__.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/protocol/selection.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/protocol/v2024_11_05.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/protocol/v2025_03_26.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/protocol/v2025_06_18.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/protocol/v2025_11_25.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/protocol/v2026_07_28.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/py.typed +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/redis.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/registry.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/request_state.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/schema.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/sessions.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/skills.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/specs.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/sqlite.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/sse.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/stdio.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/stdio_client.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/subscriptions.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/tasks.py +0 -0
- {aiohttp_tiny_mcp-0.4.0 → aiohttp_tiny_mcp-0.4.1}/src/aiohttp_tiny_mcp/testing.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aiohttp-tiny-mcp
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Remote MCP server and client library for aiohttp
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -173,8 +173,8 @@ Console("/mcp", title="Demo").setup(app, "/console")
|
|
|
173
173
|
|
|
174
174
|
Open `http://127.0.0.1:8080/console`. It speaks the protocol itself on any of
|
|
175
175
|
the five revisions, builds a form from each tool's schema, answers the
|
|
176
|
-
questions a handler asks, and shows every message either way.
|
|
177
|
-
this package
|
|
176
|
+
questions a handler asks, and shows every message either way. Static files from
|
|
177
|
+
this package need no build step or second process.
|
|
178
178
|
|
|
179
179
|
An MCP host that supports Streamable HTTP can connect to
|
|
180
180
|
`http://127.0.0.1:8080/mcp`. In an existing aiohttp service, use
|
|
@@ -235,7 +235,7 @@ Start with [the documentation overview](https://mosquito.github.io/aiohttp-tiny-
|
|
|
235
235
|
2. [Quickstart](https://mosquito.github.io/aiohttp-tiny-mcp/quickstart.html): a complete server, launch command, and client call.
|
|
236
236
|
3. [How the server fits together](https://mosquito.github.io/aiohttp-tiny-mcp/pieces.html): a conversation across two workers and each object's lifetime.
|
|
237
237
|
4. [Using Exchange](https://mosquito.github.io/aiohttp-tiny-mcp/guide/exchange.html): request context, progress, questions, and state.
|
|
238
|
-
5. [Authentication](https://mosquito.github.io/aiohttp-tiny-mcp/guide/auth.html): Basic, Bearer,
|
|
238
|
+
5. [Authentication](https://mosquito.github.io/aiohttp-tiny-mcp/guide/auth.html): Basic, Bearer, GitHub sign-in, custom policies, and permissions.
|
|
239
239
|
6. [Stores and hubs](https://mosquito.github.io/aiohttp-tiny-mcp/deployment/stores.html): shared backend contracts and deployment requirements.
|
|
240
240
|
7. [Extensions and skills](https://mosquito.github.io/aiohttp-tiny-mcp/guide/extensions.html): custom methods, skill directories, and resources for older clients.
|
|
241
241
|
|
|
@@ -131,8 +131,8 @@ Console("/mcp", title="Demo").setup(app, "/console")
|
|
|
131
131
|
|
|
132
132
|
Open `http://127.0.0.1:8080/console`. It speaks the protocol itself on any of
|
|
133
133
|
the five revisions, builds a form from each tool's schema, answers the
|
|
134
|
-
questions a handler asks, and shows every message either way.
|
|
135
|
-
this package
|
|
134
|
+
questions a handler asks, and shows every message either way. Static files from
|
|
135
|
+
this package need no build step or second process.
|
|
136
136
|
|
|
137
137
|
An MCP host that supports Streamable HTTP can connect to
|
|
138
138
|
`http://127.0.0.1:8080/mcp`. In an existing aiohttp service, use
|
|
@@ -193,7 +193,7 @@ Start with [the documentation overview](https://mosquito.github.io/aiohttp-tiny-
|
|
|
193
193
|
2. [Quickstart](https://mosquito.github.io/aiohttp-tiny-mcp/quickstart.html): a complete server, launch command, and client call.
|
|
194
194
|
3. [How the server fits together](https://mosquito.github.io/aiohttp-tiny-mcp/pieces.html): a conversation across two workers and each object's lifetime.
|
|
195
195
|
4. [Using Exchange](https://mosquito.github.io/aiohttp-tiny-mcp/guide/exchange.html): request context, progress, questions, and state.
|
|
196
|
-
5. [Authentication](https://mosquito.github.io/aiohttp-tiny-mcp/guide/auth.html): Basic, Bearer,
|
|
196
|
+
5. [Authentication](https://mosquito.github.io/aiohttp-tiny-mcp/guide/auth.html): Basic, Bearer, GitHub sign-in, custom policies, and permissions.
|
|
197
197
|
6. [Stores and hubs](https://mosquito.github.io/aiohttp-tiny-mcp/deployment/stores.html): shared backend contracts and deployment requirements.
|
|
198
198
|
7. [Extensions and skills](https://mosquito.github.io/aiohttp-tiny-mcp/guide/extensions.html): custom methods, skill directories, and resources for older clients.
|
|
199
199
|
|
|
@@ -17,6 +17,7 @@ FILES = {
|
|
|
17
17
|
"": ("index.html", "text/html"),
|
|
18
18
|
"console.js": ("console.js", "application/javascript"),
|
|
19
19
|
"console.css": ("console.css", "text/css"),
|
|
20
|
+
"oauth-callback": ("oauth-callback.html", "text/html"),
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
|
|
@@ -31,12 +32,14 @@ class Console:
|
|
|
31
32
|
description: str = "",
|
|
32
33
|
template: str | Path | None = None,
|
|
33
34
|
variables: Mapping[str, str] | None = None,
|
|
35
|
+
oauth_client_id: str | None = None,
|
|
34
36
|
) -> None:
|
|
35
37
|
self.endpoint_path = endpoint_path
|
|
36
38
|
self.title = title
|
|
37
39
|
self.description = description
|
|
38
40
|
self.template = Path(template) if template else HERE / "index.html"
|
|
39
41
|
self.variables = dict(variables or {})
|
|
42
|
+
self.oauth_client_id = oauth_client_id
|
|
40
43
|
|
|
41
44
|
def substitutions(self, base: str) -> dict[str, str]:
|
|
42
45
|
return {
|
|
@@ -44,6 +47,7 @@ class Console:
|
|
|
44
47
|
"BASE": base,
|
|
45
48
|
"TITLE": self.title,
|
|
46
49
|
"DESCRIPTION": self.description,
|
|
50
|
+
"OAUTH_CLIENT_ID": self.oauth_client_id or "",
|
|
47
51
|
**self.variables,
|
|
48
52
|
}
|
|
49
53
|
|
|
@@ -80,7 +84,7 @@ class Console:
|
|
|
80
84
|
)
|
|
81
85
|
|
|
82
86
|
def routes(self, path: str = "/console") -> list[web.RouteDef]:
|
|
83
|
-
"""The page,
|
|
87
|
+
"""The page, its assets, and the OAuth callback page."""
|
|
84
88
|
base = path.rstrip("/")
|
|
85
89
|
log.debug("console at %s, for the endpoint at %s", base, self.endpoint_path)
|
|
86
90
|
return [
|
|
@@ -89,6 +93,22 @@ class Console:
|
|
|
89
93
|
web.get(f"{base}/{{file}}", self.handle),
|
|
90
94
|
]
|
|
91
95
|
|
|
96
|
+
@staticmethod
|
|
97
|
+
def is_public(request: web.Request) -> bool:
|
|
98
|
+
"""Identify a mounted console asset for application authentication middleware.
|
|
99
|
+
|
|
100
|
+
Check the resolved handler, method, and file allowlist. No path prefix
|
|
101
|
+
is trusted, and an unmounted console grants no exemptions.
|
|
102
|
+
"""
|
|
103
|
+
handler = request.match_info.handler
|
|
104
|
+
console = getattr(handler, "__self__", None)
|
|
105
|
+
return (
|
|
106
|
+
request.method in {"GET", "HEAD"}
|
|
107
|
+
and isinstance(console, Console)
|
|
108
|
+
and handler == console.handle
|
|
109
|
+
and request.match_info.get("file", "") in FILES
|
|
110
|
+
)
|
|
111
|
+
|
|
92
112
|
def setup(self, app: web.Application, path: str = "/console") -> web.Application:
|
|
93
113
|
log.debug("adding the console routes to %r", app)
|
|
94
114
|
app.add_routes(self.routes(path))
|
|
@@ -75,7 +75,7 @@ body {
|
|
|
75
75
|
.field.grow > input { flex: 1 1 auto; min-width: 8em; }
|
|
76
76
|
.field > span { color: var(--ink-soft); font-size: 12px; }
|
|
77
77
|
|
|
78
|
-
input[type="text"], input[type="number"], select, textarea {
|
|
78
|
+
input[type="text"], input[type="password"], input[type="number"], select, textarea {
|
|
79
79
|
font: inherit;
|
|
80
80
|
color: inherit;
|
|
81
81
|
background: var(--page);
|
|
@@ -84,7 +84,7 @@ input[type="text"], input[type="number"], select, textarea {
|
|
|
84
84
|
padding: 5px 8px;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
input[type="text"]:focus, select:focus, textarea:focus, input[type="number"]:focus {
|
|
87
|
+
input[type="text"]:focus, input[type="password"]:focus, select:focus, textarea:focus, input[type="number"]:focus {
|
|
88
88
|
outline: 2px solid var(--accent);
|
|
89
89
|
outline-offset: -1px;
|
|
90
90
|
}
|
|
@@ -532,3 +532,10 @@ dialog.question #question-text p { margin: 0 0 8px; }
|
|
|
532
532
|
dialog.question #question-text :last-child { margin-bottom: 0; }
|
|
533
533
|
dialog.question menu { display: flex; justify-content: flex-end; gap: 8px; margin: 18px 0 0; padding: 0; }
|
|
534
534
|
dialog.question .argument { margin-bottom: 10px; }
|
|
535
|
+
|
|
536
|
+
.auth-field { display: flex; flex-direction: column; gap: 4px; margin: 12px 0; }
|
|
537
|
+
.auth-field[hidden] { display: none; }
|
|
538
|
+
.auth-field > input, .auth-field > select { width: 100%; min-width: 0; }
|
|
539
|
+
.auth-endpoint { overflow-wrap: anywhere; font-family: var(--mono); }
|
|
540
|
+
.auth-help { color: var(--ink-soft); font-size: 12px; }
|
|
541
|
+
.auth-error { color: var(--bad); }
|