ChatGenie
A minimal Python decorator SDK built directly on the official Model Context Protocol (MCP) Python SDK (
mcp>=2.2.0), featuring typed sync/async tools, explicit boolean safety annotations, persistent SQLite storage, Streamable HTTP transport at/mcp, loopback DNS rebinding protection, restricted CORS, and an interactive Next.js developer control center and tool playground adhering to thele-fullstackdesign tokens.
Table of Contents
- Executive Summary & Capabilities
- Exact Run Commands
- Architecture & Design
- Authentication & Security Posture
- Standalone SDK & Existing App Integration
- Report: Standard Protocol, Opportunity & Value Distinction
- Tools & Persistent SQLite Todo App
- Frontend Control Center & Playground
- Draft Agent Plugins Manifests
- Limitations
- Official Source Links
- Implementation Prompt Record
Executive Summary & Capabilities
ChatGenie was designed to bridge the gap between low-level MCP server scaffolding and developer productivity:
- Official MCP Foundation: Built directly upon the official
mcp.server.mcpserver.MCPServerinmcp>=2.2.0. Zero custom or ad-hoc JSON-RPC protocol hacks. - Minimal Python Decorator SDK: Register typed synchronous and asynchronous tools with
@genie.tool(name=..., read_only=..., destructive=...)with automatic Pydantic schema generation, docstring reflection, and exact boolean safety annotations (read_only_hint,destructive_hint,open_world_hint,idempotent_hint). ExplicitFalsevalues are strictly preserved over the wire. - Streamable HTTP Transport with DNS Rebinding Protection: Serves official MCP Streamable HTTP transport at
/mcpviaStreamableHTTPSessionManagerwith DNS rebinding protection enabled for exact loopback hosts/origins, and FastAPI CORS restricted tolocalhost:3000and127.0.0.1:3000without wildcard credentials. - Zero-Configuration SQLite Persistence: Includes an asynchronous SQLite persistence layer (
aiosqlite) that auto-initializes on first access without undocumented manual setup. Powers a complete Todo application (todo_list,todo_add,todo_complete,todo_delete) and an automatic tool execution audit log with latency benchmarking. - Standalone Lifespan Support: Exposes
genie.lifespan()andgenie.asgi_appso existing app developers can integrate ChatGenie into FastAPI or standalone scripts with minimal boilerplate (seeexamples/custom_app.py). - Deterministic Actual Tool Playground: An interactive, live testing interface in Next.js that directly invokes real MCP tool handlers over HTTP, renders dynamic input forms based on tool schemas, and inspects structured content, text content, and raw MCP JSON-RPC payloads.
- Truthful Local Security Model: Anonymous single-user mode (
noauth). Exposes no fake OAuth endpoints or fictitious RFC 9728 metadata. Employs a narrow signature lint guard against accidental model-supplied caller authentication credentials while permitting standard business resource IDs (user_id,account_id,tenant_id). - LeadEcho Visual Tokens: Clean dashboard design utilizing Inter font, exact neutral/emerald green tokens (
--primary: hsl(143 64% 37%)), white cards (shadow-[0_1px_4px_0_rgba(0,0,0,0.07)]), and a dotted gray dashboard background.
Exact Run Commands
1. Docker Compose Full-Stack (Recommended)
Start the entire production full stack (FastAPI backend + Next.js frontend) with a single command:
cd /Users/shivam/personal/chatgenie
# Build and start full stack in background
docker compose up --build -d
# Check service health and status
docker compose ps
# View live container logs
docker compose logs -f
# Shutdown stack (preserving persistent SQLite database)
docker compose down
# Shutdown stack and remove persistent volumes
docker compose down -v
Exact Running URLs:
- Frontend Control Center: http://localhost:3000
- Frontend Proxied API Status: http://localhost:3000/api/status
- Frontend Proxied MCP Endpoint: http://localhost:3000/mcp
- Frontend Interactive Todo Manager: http://localhost:3000/todos
- Frontend Tool Playground: http://localhost:3000/playground
- Frontend Schema Inspector: http://localhost:3000/inspector
- Backend Direct Health Check: http://127.0.0.1:8000/health
- Backend Direct Server Status: http://127.0.0.1:8000/api/status
- Backend Direct MCP Endpoint: http://127.0.0.1:8000/mcp
Container Architecture & Runtime Configuration:
- Local Host Binding: Ports are bound strictly to
127.0.0.1(127.0.0.1:8000:8000and127.0.0.1:3000:3000) preventing external host exposure. - Service Dependency & Healthchecks: Frontend has
depends_on: backend: condition: service_healthy. Both services employ zero-dependency lightweight healthchecks (Pythonurllib.requeston backend/healthand Node built-inhttpon frontend/). - SQLite Volume Persistence: The named volume
chatgenie-datais mounted to/datain the backend container withCHATGENIE_DB_PATH=/data/chatgenie.db. Database contents and tool execution audit logs persist across container restarts. - Dynamic Next.js Rewrites & Baked Build Handling:
- Next.js evaluates
rewrites()duringnext buildinto.next/routes-manifest.jsonand.next/required-server-files.js. - During Docker build,
ARG BACKEND_URL=http://backend:8000bakes the container service name into the production build. - At container startup,
frontend/docker-entrypoint.shinspectsBACKEND_URLand dynamically synchronizes.next/routes-manifest.jsonand.next/required-server-files.jsif overridden at runtime, enabling full container runtime configurability without rebuilds. - For local native development (
npm run dev),BACKEND_URLdefaults tohttp://127.0.0.1:8000. - In browser sessions, client API requests are sent same-origin (
/api/...and/mcp) to port 3000, where Next.js proxies tohttp://backend:8000.
- Next.js evaluates
- DNS Rebinding & CORS Protection:
- DNS rebinding guard remains active (
enable_dns_rebinding_protection=True). allowed_hostsexplicitly includes container service names (backend,backend:8000) and loopback (localhost,127.0.0.1) and can be extended withCHATGENIE_ALLOWED_HOSTS.- CORS origins are restricted to
http://localhost:3000,http://127.0.0.1:3000, andhttp://frontend:3000(orCHATGENIE_ALLOWED_ORIGINS) withallow_credentials=False. Wildcard CORS is never used.
- DNS rebinding guard remains active (
2. Local Native Development (Without Docker)
Prerequisites
- Python 3.11+ (Python 3.13 / 3.14 verified)
uv(Fast Python package manager)- Node.js 20+ (v24 verified) and
npm
Backend & MCP Server Setup
cd /Users/shivam/personal/chatgenie
# Create virtual environment and install dependencies
uv venv
uv sync --extra dev
# Run the automated pytest suite (14 tests covering real MCP ClientSession, DNS rebinding, CORS, wire annotations, and standalone usage)
uv run pytest -v
# Run the standalone custom application example
uv run python examples/custom_app.py
# Start the ChatGenie server (FastAPI + Streamable HTTP /mcp on port 8000)
uv run uvicorn chatgenie.server:app --host 127.0.0.1 --port 8000 --reload
Frontend Control Center Setup
cd /Users/shivam/personal/chatgenie/frontend
# Install dependencies
npm install
# Run linter
npm run lint
# Build production bundle
npm run build
# Start development server on port 3000
npm run dev
Architecture & Design
chatgenie/
├── chatgenie/ # Python SDK and Server Library
│ ├── __init__.py # Exports public SDK classes and helpers
│ ├── sdk.py # ChatGenie decorator SDK wrapping MCPServer
│ ├── models.py # Pydantic data models and schemas
│ ├── auth.py # Profile tool, signature lint guards, noauth configuration
│ ├── db.py # Async SQLite database layer with auto-initialization
│ ├── manifests.py # Draft Agent Plugins plugin.json and mcp.json generators
│ ├── server.py # FastAPI & ASGI app mounting /mcp with DNS rebinding protection
│ └── tools/
│ ├── __init__.py
│ ├── todo.py # Persistent SQLite todo CRUD tools
│ └── playground.py # Deterministic math, echo, timer, and profile tools
├── examples/
│ └── custom_app.py # Standalone application integration example
├── tests/ # Automated Test Suite (14 passing tests)
│ ├── test_sdk.py # Explicit boolean annotations, auto-init, custom app
│ ├── test_persistence.py # SQLite persistence across sessions
│ ├── test_mcp_client.py # Real MCP ClientSession initialize/list/call & wire annotations
│ ├── test_auth_security.py # Target IDs, lint guard, noauth, DNS rebinding, CORS
│ └── test_api.py # FastAPI REST endpoints
├── compose.yaml # Docker Compose orchestration (127.0.0.1 host binding, volumes, healthchecks)
├── Dockerfile # Minimal production backend Dockerfile (uv sync frozen, non-root user)
├── .dockerignore # Backend and root build exclusion rules
├── plugin.json # Draft Portable Agent Plugins manifest
├── mcp.json # Draft Streamable HTTP MCP manifest
├── frontend/ # Next.js 16 / React 19 UI
│ ├── Dockerfile # Multi-stage frontend Dockerfile (node:20-alpine, npm ci, non-root user)
│ ├── docker-entrypoint.sh # Dynamic runtime BACKEND_URL rewrite synchronizer
│ ├── .dockerignore # Frontend build exclusion rules
│ ├── next.config.ts # Configurable runtime rewrites (/api/:path* and /mcp)
│ ├── src/app/
│ │ ├── globals.css # Exact le-fullstack green/neutral tokens
│ │ ├── layout.tsx # Inter & JetBrains Mono fonts
│ │ └── (dashboard)/
│ │ ├── layout.tsx # Dotted gray dashboard background & sidebar
│ │ ├── dashboard/ # Overview metrics & recent execution audits
│ │ ├── playground/ # Interactive live tool invocation & inspector
│ │ ├── inspector/ # Schema inspector & annotation viewer
│ │ ├── todos/ # Persistent SQLite Todo Manager UI
│ │ ├── integration/ # Copyable code snippets & manifest files
│ │ ├── connection/ # Truthful connection instructions
│ │ └── protocol-report/# Architectural & value report
│ ├── src/components/ # Reusable sidebar and cards
│ └── src/lib/ # Frontend API client and utils
└── .agents/plugins/
└── marketplace.json # Draft local repository marketplace entry
Authentication & Security Posture
1. Truthful Scope: Local Single-User Development Mode (noauth)
ChatGenie explicitly makes no claim of being a production OAuth authorization server or production-ready multi-user system:
- Anonymous local access (
noauth): No credentials or OpenAI API keys are required for local evaluation. - No fake OAuth metadata: The server exposes no fictitious RFC 9728 metadata or nonexistent
/oauthendpoints. The/api/statusendpoint truthfully advertisesauth_mode: "noauth". - Production multi-user requirement: Multi-user enterprise deployments require placing the service behind an established authorization server (e.g. Auth0, Stytch, Okta) that validates cryptographically signed JWTs (via JWKS) at the transport layer.
2. Transport Security & Network Boundaries
To protect developers running local tool servers from web-based exploits:
- DNS Rebinding Protection: The official MCP SDK's
TransportSecuritySettingsis enabled by default. Requests to/mcpwith an externalHostheader (such asevil.com) are rejected withHTTP 421 Misdirected Request. Requests with externalOriginheaders are rejected withHTTP 403 Forbidden. Permitted hosts include loopback (localhost:8000,127.0.0.1:8000,localhost,127.0.0.1), frontend origin (localhost:3000,127.0.0.1:3000), container service hosts (backend,backend:8000), and any hosts explicitly defined viaCHATGENIE_ALLOWED_HOSTS. - Restricted CORS: FastAPI's
CORSMiddlewareis strictly restricted tohttp://localhost:3000,http://127.0.0.1:3000, andhttp://frontend:3000(orCHATGENIE_ALLOWED_ORIGINS) withallow_credentials=False. No wildcard origins or wildcard credentials are ever permitted.
3. Tool Signature Lint Guard vs. Authorization
- Not Zero-Trust Authorization: Static parameter inspection is strictly a development lint guard to catch common parameter naming mistakes. It is not an authorization mechanism.
- Target Resource IDs Permitted: Legitimate target resource identifiers such as
user_id,account_id, andtenant_idare standard business arguments and are fully permitted. - Caller Credential Detection: The lint guard flags parameter names that resemble caller authentication session tokens (e.g.
caller_id,auth_user), warning developers that caller authentication must be resolved from request credentials rather than passed as untrusted model arguments.
4. Standard Profile Tool
ChatGenie provides a get_profile tool conforming to OpenAI's profile schema with _meta["openai/profile"]: true:
{
"id": "usr_local_single_user",
"name": "Local Developer",
"email": "developer@chatgenie.local",
"nickname": "Local Dev (Single-User)"
}
The opaque ID remains stable across reconnects in local single-user mode.
Standalone SDK & Existing App Integration
Existing application developers can import and use ChatGenie in standalone scripts or FastAPI services without any undocumented database setup:
import asyncio
from chatgenie import ChatGenie
# Tables automatically initialize on first call or via lifespan
genie = ChatGenie(name="my-service", db_path="my_service.db")
@genie.tool(
name="calculate_discount",
title="Calculate Discount",
description="Calculate final price after discount.",
read_only=True,
idempotent=True,
)
def calculate_discount(price: float, discount_percent: float) -> dict:
savings = round(price * (discount_percent / 100.0), 2)
return {"final_price": round(price - savings, 2), "savings": savings}
async def main():
async with genie.lifespan():
resp = await genie.call_tool(
"calculate_discount",
{"price": 100.0, "discount_percent": 15.0},
)
print(resp.result)
if __name__ == "__main__":
asyncio.run(main())
See examples/custom_app.py for the complete runnable example verified by the automated test suite.
Report: Standard Protocol, Opportunity & Value Distinction
1. Standard Protocol Architecture
Early LLM tool frameworks used proprietary, ad-hoc HTTP endpoints (/call-phantom-function) without standardized lifecycle negotiation, session management, or transport streaming.
The Model Context Protocol (MCP) replaces fragmented approaches with an open, formal specification:
- Streamable HTTP Transport (
/mcp): Operates over standard HTTP with server-sent events or chunked streams, handling bi-directional communication, request batching, and session identification without custom sockets. - Strict Lifecycle Handshake: Handshakes via
initializeto negotiate protocol version, advertised capabilities (tools, resources, prompts, logging), and server instructions before accepting commands. - Rich Result Schema: Returns typed
structuredContentfor model reasoning, human-readablecontentblocks for conversation flow, and out-of-band_metablocks for client-specific handling.
2. The Platform & Ecosystem Opportunity
Standardizing on MCP gives developers single-implementation leverage across the entire AI ecosystem:
- ChatGPT & Codex: Connects directly via ChatGPT Developer Mode (
https://chatgpt.com/plugins), Codex CLI, or Agent Plugins marketplaces. - Claude & IDEs: Operates natively with Claude Desktop, Cursor, and Windsurf via standard MCP config.
- Autonomous Multi-Agent Systems: Provides clean discoverability via
tools/listwith typed schemas and safety hints so autonomous planner agents can safely choose tools.
3. Distinguishing Raw MCP SDK Capabilities from ChatGenie Value
| Architectural Dimension | Official MCP Python SDK (mcp 2.2.0) |
ChatGenie Value Layer |
|---|---|---|
| Tool Decorator | Low-level @server.tool() requiring manual ToolAnnotations object construction. |
Developer-friendly @genie.tool() preserving explicit boolean hints (read_only=False, destructive=False), automatic metadata enrichment, and docstring inference. |
| Transport Security & Network | Provides unconfigured TransportSecuritySettings. |
Out-of-the-box DNS rebinding protection for loopback hosts and restricted CORS without wildcard credentials. |
| State & Persistence | Completely stateless. Database connectivity and transaction handling are unaddressed. | Integrated asynchronous SQLite layer (aiosqlite) with automatic initialization, persistent todo CRUD, and automated tool execution audit logging. |
| Testing & Developer Experience | Requires running external Node.js CLI packages (npx @modelcontextprotocol/inspector). |
Embedded interactive Next.js Tool Playground with live schema form rendering, latency benchmarking, and raw JSON-RPC inspection in-browser. |
| Framework Integration & Packaging | Returns separate Starlette app; requires manual ASGI wiring for dual REST+MCP APIs. | Turnkey genie.lifespan() and genie.asgi_app integration for FastAPI/ASGI, plus draft Agent Plugins packaging (plugin.json and mcp.json). |
Tools & Persistent SQLite Todo App
ChatGenie provides 8 active tools registered through the SDK:
SQLite Todo Tools
todo_list(status: "all" | "pending" | "completed" = "all", limit: int = 50)- Annotation:
readOnlyHint: true - Queries
todostable in SQLite, returnsTodoListResponsewith counts.
- Annotation:
todo_add(title: str, description: str = "", priority: "low" | "medium" | "high" = "medium")- Annotation:
readOnlyHint: false, destructiveHint: false - Inserts task into SQLite with UTC timestamps, returns created item.
- Annotation:
todo_complete(todo_id: int)- Annotation:
readOnlyHint: false, destructiveHint: false - Sets status to
'completed'and recordscompleted_atin SQLite.
- Annotation:
todo_delete(todo_id: int)- Annotation:
readOnlyHint: false, destructiveHint: true - Removes task permanently from SQLite.
- Annotation:
Deterministic Test & Utility Tools
get_profile()- Annotation:
readOnlyHint: true, _meta: {"openai/profile": true} - Returns standard OpenAI profile schema for single-user local demo.
- Annotation:
echo_tool(message: str)- Annotation:
readOnlyHint: true, idempotentHint: true - Synchronous echo testing deterministic serialization.
- Annotation:
calculate(operation: "add"|"subtract"|"multiply"|"divide"|"power", a: float, b: float)- Annotation:
readOnlyHint: true, idempotentHint: true - Exact mathematical computation with division-by-zero validation.
- Annotation:
async_timer(task_name: str, delay_ms: int = 50)- Annotation:
readOnlyHint: true - Asynchronous sleep testing non-blocking event-loop concurrency.
- Annotation:
Frontend Control Center & Playground
Built using Next.js 16 (App Router), React 19, and Tailwind CSS v4, styled strictly according to le-fullstack tokens:
- Tokens: Emerald primary (
hsl(143 64% 37%)), neutral dark text (hsl(0 0% 7%)), subtle borders (hsl(0 0% 90%)), and muted backgrounds (hsl(220 14% 97%)). - Dotted Background: Radial gradient dot-matrix styling:
radial-gradient(circle, hsl(220 13% 82%) 1px, transparent 1px) 20px 20px. - White Cards: Rounded corners (
rounded-xl) with subtle border and elevation (shadow-[0_1px_4px_0_rgba(0,0,0,0.07)]). - Sidebar: Left navigation with collapsible items, status indicators, and noauth notices.
- Dynamic Form Playground: Automatically renders inputs, number steppers, dropdowns, and checkboxes mapped to tool
input_schemaproperties.
Draft Agent Plugins Manifests
ChatGenie generates draft manifest files conforming to the current OpenAI Package Plugin and Agent Plugins specifications for local development testing:
plugin.json (Draft)
Conforms to https://agent-plugins.org/schemas/1.0.0/plugin.schema.json:
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "chatgenie",
"version": "1.0.0",
"description": "Minimal Python decorator SDK on official MCP SDK with persistent SQLite todo and tool playground (draft local packaging).",
"extensions": {
"com.openai": {
"interface": {
"displayName": "ChatGenie (Draft)",
"shortDescription": "Minimal Python decorator SDK on official MCP with persistent SQLite.",
"brandColor": "#16a34a"
}
}
}
}
mcp.json (Draft)
Conforms to https://agent-plugins.org/schemas/1.0.0/mcp.schema.json:
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
"mcpServers": {
"chatgenie": {
"type": "streamable-http",
"url": "http://localhost:8000/mcp",
"description": "ChatGenie Streamable HTTP MCP Server"
}
}
}
Limitations
- Local Single-User Scope: The prototype runs in local single-user mode (
noauth). It does not issue production OAuth 2.1 access tokens or provide multi-user tenant isolation. - Public Reachability for Cloud Clients: Connecting to ChatGPT Developer Mode from ChatGPT's cloud servers requires exposing port 8000 through an HTTPS forwarding tunnel (such as OpenAI Secure MCP Tunnel or Cloudflare Tunnel) because cloud workers cannot reach private local loopback addresses directly. Local tools (such as MCP Inspector and local pytest suites) connect directly to
http://127.0.0.1:8000/mcp. - No External LLM API Key Included: ChatGenie focuses on the server, SDK, persistence, schema inspection, and tool playground layers. It does not require or bundle an external model provider API key.
Official Source Links
- OpenAI Build an MCP Server: https://developers.openai.com/plugins/build/mcp-server
- OpenAI Package Your Plugin: https://developers.openai.com/plugins/build/plugins
- OpenAI Authentication Guide: https://developers.openai.com/plugins/build/auth
- OpenAI Connect & Test Plugins: https://developers.openai.com/plugins/deploy/connect-chatgpt
- Model Context Protocol Specification: https://modelcontextprotocol.io
- Official MCP Python SDK: https://github.com/modelcontextprotocol/python-sdk
Implementation Prompt Record
The entire ChatGenie codebase and verification suite were created and refined under the following specifications:
Review and fix ONLY /Users/shivam/personal/chatgenie. Prior pass produced prototype. Concrete review findings: sdk.py tool annotations incorrectly turn false into None; preserve explicit booleans and assert wire annotations in real MCP test. Remove fake OAuth protected resource metadata referencing nonexistent /oauth and all claims RFC9728 advertised; anonymous local demo should advertise noauth and no OAuth endpoints. Enable DNS rebinding protection with exact loopback hosts/origins for demo (tests too), restrict CORS to localhost:3000 and 127.0.0.1:3000, no wildcard credentials; test rejected external origin/Host. Security signature-name blacklist is not zero-trust authorization and rejects legitimate target resource IDs; remove or narrowly describe as lint guard, do not market as auth or ban all target IDs. Audit README/UI/manifests for unsupported production/readiness/security statements. Align generated plugin packaging exactly to official current package-plugin docs; if unvalidated label packaging draft or remove rather than fabricate. Main SDK must usable by existing app developer in small standalone example incl lifespan/db initialization; provide examples/custom_app.py and test that documented snippet initializes and calls decorated custom function without undocumented db setup. Keep modifications small. Run backend tests, frontend lint/build, save concise VALIDATION.md with exact output and limitations. Do not delegate or modify references or credentials or publish. All code fixes by you. No additional speculative features. Return concise results.
Metadata
Release files for chatgenie 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| chatgenie-0.1.0.tar.gz | 140.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| chatgenie-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 176.1 kB
Release files / chatgenie-0.1.0.tar.gz
| Download URL | chatgenie-0.1.0.tar.gz |
|---|---|
| Size | 140.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7c6b3e4c9c46301f6052f4ad434c275010a2f1ec30677e175e3ff7189cf05f17
|
|
BLAKE2b-256 checksum How to use checksums |
f2037a1cdb966ebd3690ebb5d7108c971d9bd6de07e3565e6e98ec1098505577
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / chatgenie-0.1.0-py3-none-any.whl
| Download URL | chatgenie-0.1.0-py3-none-any.whl |
|---|---|
| Size | 35.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e78d22a9ac0c93f4318556cbd5fb71a7fd3210a1dda59566bd7b1cb258ec26d0
|
|
BLAKE2b-256 checksum How to use checksums |
5596c4af3089ca0c90e5cbddb8e17d77d08726a3776313c7ecd34e241b2025ef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|