From 9929f053343d0170e13976c04320ca32ab69349f Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Sun, 11 Oct 2026 23:37:46 +0530 Subject: [PATCH] refactor: serve MCP bundles under /mcp with nginx guard; rename core->mcp_server - collect.py: copy repo MCP bundles to ROOT//mcp (instead of ROOT/mcp/); add nginx location guard to deny //mcp/ - config.py: bundle roots now point to /mcp and standards/mcp for static bundles - Rename core.py -> mcp_server.py and update imports in main.py and registry.py - Dockerfile: per-repo MCP COPYs under /app//mcp, drop blog copy; add ports 8008/8009 in .drone.yml - Restore standards/mcp/libraries.json from git for registry server --- .drone.yml | 2 + Dockerfile | 2 +- collect.py | 6 +- config.py | 2 +- {mcp/dagpipe => dagpipe/mcp}/index.json | 0 .../mcp}/modules/dagpipe.engine.json | 0 .../mcp}/modules/dagpipe.graph.json | 0 .../mcp}/modules/dagpipe.json | 0 .../mcp}/modules/dagpipe.node.json | 0 .../mcp}/modules/dagpipe.state.json | 0 .../mcp}/modules/dagpipe.yaml_loader.json | 0 {mcp/dagpipe => dagpipe/mcp}/nav.json | 0 {mcp/doc-forge => doc-forge/mcp}/index.json | 0 .../mcp}/modules/docforge.cli.api_utils.json | 0 .../mcp}/modules/docforge.cli.commands.json | 0 .../mcp}/modules/docforge.cli.json | 0 .../mcp}/modules/docforge.cli.main.json | 0 .../mcp}/modules/docforge.cli.mcp_utils.json | 0 .../modules/docforge.cli.mkdocs_utils.json | 0 .../mcp}/modules/docforge.json | 0 .../docforge.loaders.griffe_loader.json | 0 .../mcp}/modules/docforge.loaders.json | 0 .../mcp}/modules/docforge.models.json | 0 .../mcp}/modules/docforge.models.module.json | 0 .../mcp}/modules/docforge.models.object.json | 0 .../mcp}/modules/docforge.models.project.json | 0 .../mcp}/modules/docforge.nav.json | 0 .../mcp}/modules/docforge.nav.mkdocs.json | 0 .../mcp}/modules/docforge.nav.resolver.json | 0 .../mcp}/modules/docforge.nav.spec.json | 0 .../mcp}/modules/docforge.nav.wiki.json | 0 .../mcp}/modules/docforge.renderers.base.json | 0 .../mcp}/modules/docforge.renderers.json | 0 .../docforge.renderers.mcp_renderer.json | 0 .../docforge.renderers.mkdocs_renderer.json | 0 .../mcp}/modules/docforge.servers.json | 0 .../modules/docforge.servers.mcp_server.json | 0 {mcp/doc-forge => doc-forge/mcp}/nav.json | 0 {mcp/hexa => hexa/mcp}/index.json | 0 .../mcp}/modules/hexa.check_matches.json | 0 {mcp/hexa => hexa/mcp}/modules/hexa.cli.json | 0 .../mcp}/modules/hexa.container.json | 0 .../mcp}/modules/hexa.generate_abc.json | 0 .../mcp}/modules/hexa.generate_yaml.json | 0 {mcp/hexa => hexa/mcp}/modules/hexa.json | 0 .../hexa => hexa/mcp}/modules/hexa.model.json | 0 .../mcp}/modules/hexa.parse_abc.json | 0 .../mcp}/modules/hexa.parse_yaml.json | 0 {mcp/hexa => hexa/mcp}/nav.json | 0 .../mcp}/index.json | 0 .../modules/mail_intake.adapters.base.json | 0 .../modules/mail_intake.adapters.gmail.json | 0 .../mcp}/modules/mail_intake.adapters.json | 0 .../mcp}/modules/mail_intake.auth.base.json | 0 .../mcp}/modules/mail_intake.auth.google.json | 0 .../mcp}/modules/mail_intake.auth.json | 0 .../mcp}/modules/mail_intake.config.json | 0 .../mcp}/modules/mail_intake.credentials.json | 0 .../mail_intake.credentials.pickle.json | 0 .../mail_intake.credentials.redis.json | 0 .../mail_intake.credentials.store.json | 0 .../mcp}/modules/mail_intake.exceptions.json | 0 .../mcp}/modules/mail_intake.ingestion.json | 0 .../modules/mail_intake.ingestion.reader.json | 0 .../mcp}/modules/mail_intake.json | 0 .../mcp}/modules/mail_intake.models.json | 0 .../modules/mail_intake.models.message.json | 0 .../modules/mail_intake.models.thread.json | 0 .../modules/mail_intake.parsers.body.json | 0 .../modules/mail_intake.parsers.headers.json | 0 .../mcp}/modules/mail_intake.parsers.json | 0 .../modules/mail_intake.parsers.subject.json | 0 {mcp/mail-intake => mail-intake/mcp}/nav.json | 0 main.py | 2 +- mcp/standards/libraries.json | 78 ------------------ core.py => mcp_server.py | 0 {mcp/mongo-ops => mongo-ops/mcp}/index.json | 0 .../mcp}/modules/mongo_ops.cache.backend.json | 0 .../mcp}/modules/mongo_ops.cache.config.json | 0 .../modules/mongo_ops.cache.in_memory.json | 0 .../mcp}/modules/mongo_ops.cache.json | 0 .../mongo_ops.cache.redis_backend.json | 0 .../modules/mongo_ops.cache.repository.json | 0 .../mcp}/modules/mongo_ops.connection.json | 0 .../mcp}/modules/mongo_ops.json | 0 .../mcp}/modules/mongo_ops.models.json | 0 .../modules/mongo_ops.populate.engine.json | 0 .../mcp}/modules/mongo_ops.populate.json | 0 .../modules/mongo_ops.populate.rules.json | 0 .../mcp}/modules/mongo_ops.registry.json | 0 .../mcp}/modules/mongo_ops.repository.json | 0 .../mcp}/modules/mongo_ops.transactions.json | 0 {mcp/mongo-ops => mongo-ops/mcp}/nav.json | 0 nginx.conf | 4 + {mcp/omniread => omniread/mcp}/index.json | 0 .../mcp}/modules/omniread.core.content.json | 0 .../mcp}/modules/omniread.core.json | 0 .../mcp}/modules/omniread.core.parser.json | 0 .../mcp}/modules/omniread.core.scraper.json | 0 .../mcp}/modules/omniread.csv.client.json | 0 .../mcp}/modules/omniread.csv.json | 0 .../mcp}/modules/omniread.csv.parser.json | 0 .../modules/omniread.csv.parser_base.json | 0 .../mcp}/modules/omniread.csv.scraper.json | 0 .../mcp}/modules/omniread.html.json | 0 .../mcp}/modules/omniread.html.parser.json | 0 .../mcp}/modules/omniread.html.scraper.json | 0 .../mcp}/modules/omniread.json | 0 .../mcp}/modules/omniread.pdf.client.json | 0 .../mcp}/modules/omniread.pdf.json | 0 .../mcp}/modules/omniread.pdf.parser.json | 0 .../mcp}/modules/omniread.pdf.scraper.json | 0 .../mcp}/modules/omniread.xlsx.client.json | 0 .../mcp}/modules/omniread.xlsx.json | 0 .../mcp}/modules/omniread.xlsx.parser.json | 0 .../modules/omniread.xlsx.parser_base.json | 0 .../mcp}/modules/omniread.xlsx.scraper.json | 0 {mcp/omniread => omniread/mcp}/nav.json | 0 .../mcp}/index.json | 0 .../mcp}/modules/openapi_first.app.json | 0 .../mcp}/modules/openapi_first.binder.json | 0 .../mcp}/modules/openapi_first.cli.json | 0 .../mcp}/modules/openapi_first.client.json | 0 .../mcp}/modules/openapi_first.codegen.json | 0 .../modules/openapi_first.codegen_routes.json | 0 .../mcp}/modules/openapi_first.errors.json | 0 .../mcp}/modules/openapi_first.json | 0 .../mcp}/modules/openapi_first.loader.json | 0 .../mcp}/modules/openapi_first.security.json | 0 ...openapi_first.templates.crud_app.data.json | 0 .../openapi_first.templates.crud_app.json | 0 ...openapi_first.templates.crud_app.main.json | 0 ...enapi_first.templates.crud_app.routes.json | 0 ...irst.templates.crud_app.test_crud_app.json | 0 .../openapi_first.templates.health_app.json | 0 ...enapi_first.templates.health_app.main.json | 0 ...api_first.templates.health_app.routes.json | 0 .../mcp}/modules/openapi_first.templates.json | 0 ...penapi_first.templates.model_app.data.json | 0 .../openapi_first.templates.model_app.json | 0 ...penapi_first.templates.model_app.main.json | 0 ...napi_first.templates.model_app.models.json | 0 ...napi_first.templates.model_app.routes.json | 0 ...st.templates.model_app.test_model_app.json | 0 .../openapi_first.templates.vet_app.data.json | 0 .../openapi_first.templates.vet_app.json | 0 .../openapi_first.templates.vet_app.main.json | 0 ...penapi_first.templates.vet_app.models.json | 0 ...penapi_first.templates.vet_app.routes.json | 0 .../openapi_first.templates.vet_app.sse.json | 0 ..._first.templates.vet_app.test_vet_app.json | 0 .../mcp}/nav.json | 0 {mcp/py-jwt => py-jwt/mcp}/index.json | 0 .../mcp}/modules/jwtlib.app.json | 0 .../mcp}/modules/jwtlib.exceptions.json | 0 .../mcp}/modules/jwtlib.introspection.json | 0 .../py-jwt => py-jwt/mcp}/modules/jwtlib.json | 0 .../mcp}/modules/jwtlib.models.app.json | 0 .../mcp}/modules/jwtlib.models.common.json | 0 .../mcp}/modules/jwtlib.models.json | 0 .../mcp}/modules/jwtlib.models.mongo.json | 0 .../mcp}/modules/jwtlib.models.security.json | 0 .../mcp}/modules/jwtlib.repository.json | 0 .../mcp}/modules/jwtlib.security.json | 0 .../mcp}/modules/jwtlib.utils.json | 0 {mcp/py-jwt => py-jwt/mcp}/nav.json | 0 registry.py | 2 +- {mcp/standards => standards/mcp}/index.json | 0 standards/mcp/libraries.json | Bin 0 -> 7464 bytes .../mcp}/modules/composition_root.json | 0 .../mcp}/modules/crud_template.json | 0 .../mcp}/modules/genericity_matrix.json | 0 .../mcp}/modules/human_in_loop.json | 0 .../mcp}/modules/index.json | 0 .../mcp}/modules/infra_adaptors.json | 0 .../mcp}/modules/layering_rules.json | 0 .../mcp}/modules/library_registry.json | 0 .../mcp}/modules/pipeline_scaffold.json | 0 .../mcp}/modules/spec_first_routing.json | 0 .../mcp}/modules/worker_and_progress.json | 0 {mcp/standards => standards/mcp}/nav.json | 0 standards/mcp/standards/index.json | 6 ++ .../standards/modules/composition_root.json | 8 ++ .../mcp/standards/modules/crud_template.json | 8 ++ .../standards/modules/genericity_matrix.json | 8 ++ .../mcp/standards/modules/human_in_loop.json | 8 ++ standards/mcp/standards/modules/index.json | 8 ++ .../mcp/standards/modules/infra_adaptors.json | 8 ++ .../mcp/standards/modules/layering_rules.json | 8 ++ .../standards/modules/library_registry.json | 8 ++ .../standards/modules/pipeline_scaffold.json | 8 ++ .../standards/modules/spec_first_routing.json | 8 ++ .../modules/worker_and_progress.json | 8 ++ standards/mcp/standards/nav.json | 57 +++++++++++++ 194 files changed, 166 insertions(+), 83 deletions(-) rename {mcp/dagpipe => dagpipe/mcp}/index.json (100%) rename {mcp/dagpipe => dagpipe/mcp}/modules/dagpipe.engine.json (100%) rename {mcp/dagpipe => dagpipe/mcp}/modules/dagpipe.graph.json (100%) rename {mcp/dagpipe => dagpipe/mcp}/modules/dagpipe.json (100%) rename {mcp/dagpipe => dagpipe/mcp}/modules/dagpipe.node.json (100%) rename {mcp/dagpipe => dagpipe/mcp}/modules/dagpipe.state.json (100%) rename {mcp/dagpipe => dagpipe/mcp}/modules/dagpipe.yaml_loader.json (100%) rename {mcp/dagpipe => dagpipe/mcp}/nav.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/index.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.cli.api_utils.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.cli.commands.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.cli.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.cli.main.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.cli.mcp_utils.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.cli.mkdocs_utils.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.loaders.griffe_loader.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.loaders.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.models.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.models.module.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.models.object.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.models.project.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.nav.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.nav.mkdocs.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.nav.resolver.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.nav.spec.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.nav.wiki.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.renderers.base.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.renderers.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.renderers.mcp_renderer.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.renderers.mkdocs_renderer.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.servers.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/modules/docforge.servers.mcp_server.json (100%) rename {mcp/doc-forge => doc-forge/mcp}/nav.json (100%) rename {mcp/hexa => hexa/mcp}/index.json (100%) rename {mcp/hexa => hexa/mcp}/modules/hexa.check_matches.json (100%) rename {mcp/hexa => hexa/mcp}/modules/hexa.cli.json (100%) rename {mcp/hexa => hexa/mcp}/modules/hexa.container.json (100%) rename {mcp/hexa => hexa/mcp}/modules/hexa.generate_abc.json (100%) rename {mcp/hexa => hexa/mcp}/modules/hexa.generate_yaml.json (100%) rename {mcp/hexa => hexa/mcp}/modules/hexa.json (100%) rename {mcp/hexa => hexa/mcp}/modules/hexa.model.json (100%) rename {mcp/hexa => hexa/mcp}/modules/hexa.parse_abc.json (100%) rename {mcp/hexa => hexa/mcp}/modules/hexa.parse_yaml.json (100%) rename {mcp/hexa => hexa/mcp}/nav.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/index.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.adapters.base.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.adapters.gmail.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.adapters.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.auth.base.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.auth.google.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.auth.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.config.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.credentials.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.credentials.pickle.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.credentials.redis.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.credentials.store.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.exceptions.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.ingestion.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.ingestion.reader.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.models.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.models.message.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.models.thread.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.parsers.body.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.parsers.headers.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.parsers.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/modules/mail_intake.parsers.subject.json (100%) rename {mcp/mail-intake => mail-intake/mcp}/nav.json (100%) delete mode 100644 mcp/standards/libraries.json rename core.py => mcp_server.py (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/index.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.cache.backend.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.cache.config.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.cache.in_memory.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.cache.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.cache.redis_backend.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.cache.repository.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.connection.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.models.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.populate.engine.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.populate.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.populate.rules.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.registry.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.repository.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/modules/mongo_ops.transactions.json (100%) rename {mcp/mongo-ops => mongo-ops/mcp}/nav.json (100%) rename {mcp/omniread => omniread/mcp}/index.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.core.content.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.core.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.core.parser.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.core.scraper.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.csv.client.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.csv.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.csv.parser.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.csv.parser_base.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.csv.scraper.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.html.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.html.parser.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.html.scraper.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.pdf.client.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.pdf.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.pdf.parser.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.pdf.scraper.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.xlsx.client.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.xlsx.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.xlsx.parser.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.xlsx.parser_base.json (100%) rename {mcp/omniread => omniread/mcp}/modules/omniread.xlsx.scraper.json (100%) rename {mcp/omniread => omniread/mcp}/nav.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/index.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.app.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.binder.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.cli.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.client.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.codegen.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.codegen_routes.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.errors.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.loader.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.security.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.crud_app.data.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.crud_app.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.crud_app.main.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.crud_app.routes.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.crud_app.test_crud_app.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.health_app.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.health_app.main.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.health_app.routes.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.model_app.data.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.model_app.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.model_app.main.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.model_app.models.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.model_app.routes.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.model_app.test_model_app.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.vet_app.data.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.vet_app.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.vet_app.main.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.vet_app.models.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.vet_app.routes.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.vet_app.sse.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/modules/openapi_first.templates.vet_app.test_vet_app.json (100%) rename {mcp/openapi-first => openapi-first/mcp}/nav.json (100%) rename {mcp/py-jwt => py-jwt/mcp}/index.json (100%) rename {mcp/py-jwt => py-jwt/mcp}/modules/jwtlib.app.json (100%) rename {mcp/py-jwt => py-jwt/mcp}/modules/jwtlib.exceptions.json (100%) rename {mcp/py-jwt => py-jwt/mcp}/modules/jwtlib.introspection.json (100%) rename {mcp/py-jwt => py-jwt/mcp}/modules/jwtlib.json (100%) rename {mcp/py-jwt => py-jwt/mcp}/modules/jwtlib.models.app.json (100%) rename {mcp/py-jwt => py-jwt/mcp}/modules/jwtlib.models.common.json (100%) rename {mcp/py-jwt => py-jwt/mcp}/modules/jwtlib.models.json (100%) rename {mcp/py-jwt => py-jwt/mcp}/modules/jwtlib.models.mongo.json (100%) rename {mcp/py-jwt => py-jwt/mcp}/modules/jwtlib.models.security.json (100%) rename {mcp/py-jwt => py-jwt/mcp}/modules/jwtlib.repository.json (100%) rename {mcp/py-jwt => py-jwt/mcp}/modules/jwtlib.security.json (100%) rename {mcp/py-jwt => py-jwt/mcp}/modules/jwtlib.utils.json (100%) rename {mcp/py-jwt => py-jwt/mcp}/nav.json (100%) rename {mcp/standards => standards/mcp}/index.json (100%) create mode 100644 standards/mcp/libraries.json rename {mcp/standards => standards/mcp}/modules/composition_root.json (100%) rename {mcp/standards => standards/mcp}/modules/crud_template.json (100%) rename {mcp/standards => standards/mcp}/modules/genericity_matrix.json (100%) rename {mcp/standards => standards/mcp}/modules/human_in_loop.json (100%) rename {mcp/standards => standards/mcp}/modules/index.json (100%) rename {mcp/standards => standards/mcp}/modules/infra_adaptors.json (100%) rename {mcp/standards => standards/mcp}/modules/layering_rules.json (100%) rename {mcp/standards => standards/mcp}/modules/library_registry.json (100%) rename {mcp/standards => standards/mcp}/modules/pipeline_scaffold.json (100%) rename {mcp/standards => standards/mcp}/modules/spec_first_routing.json (100%) rename {mcp/standards => standards/mcp}/modules/worker_and_progress.json (100%) rename {mcp/standards => standards/mcp}/nav.json (100%) create mode 100644 standards/mcp/standards/index.json create mode 100644 standards/mcp/standards/modules/composition_root.json create mode 100644 standards/mcp/standards/modules/crud_template.json create mode 100644 standards/mcp/standards/modules/genericity_matrix.json create mode 100644 standards/mcp/standards/modules/human_in_loop.json create mode 100644 standards/mcp/standards/modules/index.json create mode 100644 standards/mcp/standards/modules/infra_adaptors.json create mode 100644 standards/mcp/standards/modules/layering_rules.json create mode 100644 standards/mcp/standards/modules/library_registry.json create mode 100644 standards/mcp/standards/modules/pipeline_scaffold.json create mode 100644 standards/mcp/standards/modules/spec_first_routing.json create mode 100644 standards/mcp/standards/modules/worker_and_progress.json create mode 100644 standards/mcp/standards/nav.json diff --git a/.drone.yml b/.drone.yml index 609aa3d..81408b2 100644 --- a/.drone.yml +++ b/.drone.yml @@ -74,6 +74,8 @@ steps: -p 8005:8005 \ -p 8006:8006 \ -p 8007:8007 \ + -p 8008:8008 \ + -p 8009:8009 \ --restart always \ aetos/docs:latest diff --git a/Dockerfile b/Dockerfile index d77d263..ad175c7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,7 @@ RUN pip install --no-cache-dir uv && \ uv pip install --system -r requirements.txt # --- application files ----------------------------------------------------- -COPY main.py core.py config.py registry.py collect.py config.yml ./ +COPY main.py mcp_server.py config.py registry.py collect.py config.yml ./ COPY nginx.conf /etc/nginx/conf.d/default.conf RUN rm -f /etc/nginx/sites-enabled/default diff --git a/collect.py b/collect.py index 34f28c1..0eb2403 100644 --- a/collect.py +++ b/collect.py @@ -256,6 +256,10 @@ NGINX_TEMPLATE = r"""server {{ root /usr/share/nginx/html; index index.html lib/index.html api/index.html; + location ~ ^/[^/]+/mcp/ {{ + deny all; + }} + location / {{ try_files $uri $uri/ /index.html; }} @@ -316,7 +320,7 @@ def collect(config: dict, dry_run: bool = False) -> list[str]: if not src.is_dir(): errors.append(f"{name}: mcp bundle missing ({src})") continue - dst = ROOT / MCP_DIR / name + dst = ROOT / name / MCP_DIR copied.append(f" mcp {name} {dst.relative_to(ROOT)}/") if not dry_run: _copy_dir(src, dst) diff --git a/config.py b/config.py index 19fb499..b8551b5 100644 --- a/config.py +++ b/config.py @@ -39,7 +39,7 @@ class ServiceConfig: """Return every MCP server: one per repo that declares a bundle, plus the hand-authored static servers (for example the standards registry).""" servers: dict[str, MCPBundle] = { - r.name: MCPBundle(root=Path("mcp") / r.name, name=r.mcp_server, port=r.mcp_port) + r.name: MCPBundle(root=Path(r.name) / "mcp", name=r.mcp_server, port=r.mcp_port) for r in self.repos if r.mcp_port is not None } diff --git a/mcp/dagpipe/index.json b/dagpipe/mcp/index.json similarity index 100% rename from mcp/dagpipe/index.json rename to dagpipe/mcp/index.json diff --git a/mcp/dagpipe/modules/dagpipe.engine.json b/dagpipe/mcp/modules/dagpipe.engine.json similarity index 100% rename from mcp/dagpipe/modules/dagpipe.engine.json rename to dagpipe/mcp/modules/dagpipe.engine.json diff --git a/mcp/dagpipe/modules/dagpipe.graph.json b/dagpipe/mcp/modules/dagpipe.graph.json similarity index 100% rename from mcp/dagpipe/modules/dagpipe.graph.json rename to dagpipe/mcp/modules/dagpipe.graph.json diff --git a/mcp/dagpipe/modules/dagpipe.json b/dagpipe/mcp/modules/dagpipe.json similarity index 100% rename from mcp/dagpipe/modules/dagpipe.json rename to dagpipe/mcp/modules/dagpipe.json diff --git a/mcp/dagpipe/modules/dagpipe.node.json b/dagpipe/mcp/modules/dagpipe.node.json similarity index 100% rename from mcp/dagpipe/modules/dagpipe.node.json rename to dagpipe/mcp/modules/dagpipe.node.json diff --git a/mcp/dagpipe/modules/dagpipe.state.json b/dagpipe/mcp/modules/dagpipe.state.json similarity index 100% rename from mcp/dagpipe/modules/dagpipe.state.json rename to dagpipe/mcp/modules/dagpipe.state.json diff --git a/mcp/dagpipe/modules/dagpipe.yaml_loader.json b/dagpipe/mcp/modules/dagpipe.yaml_loader.json similarity index 100% rename from mcp/dagpipe/modules/dagpipe.yaml_loader.json rename to dagpipe/mcp/modules/dagpipe.yaml_loader.json diff --git a/mcp/dagpipe/nav.json b/dagpipe/mcp/nav.json similarity index 100% rename from mcp/dagpipe/nav.json rename to dagpipe/mcp/nav.json diff --git a/mcp/doc-forge/index.json b/doc-forge/mcp/index.json similarity index 100% rename from mcp/doc-forge/index.json rename to doc-forge/mcp/index.json diff --git a/mcp/doc-forge/modules/docforge.cli.api_utils.json b/doc-forge/mcp/modules/docforge.cli.api_utils.json similarity index 100% rename from mcp/doc-forge/modules/docforge.cli.api_utils.json rename to doc-forge/mcp/modules/docforge.cli.api_utils.json diff --git a/mcp/doc-forge/modules/docforge.cli.commands.json b/doc-forge/mcp/modules/docforge.cli.commands.json similarity index 100% rename from mcp/doc-forge/modules/docforge.cli.commands.json rename to doc-forge/mcp/modules/docforge.cli.commands.json diff --git a/mcp/doc-forge/modules/docforge.cli.json b/doc-forge/mcp/modules/docforge.cli.json similarity index 100% rename from mcp/doc-forge/modules/docforge.cli.json rename to doc-forge/mcp/modules/docforge.cli.json diff --git a/mcp/doc-forge/modules/docforge.cli.main.json b/doc-forge/mcp/modules/docforge.cli.main.json similarity index 100% rename from mcp/doc-forge/modules/docforge.cli.main.json rename to doc-forge/mcp/modules/docforge.cli.main.json diff --git a/mcp/doc-forge/modules/docforge.cli.mcp_utils.json b/doc-forge/mcp/modules/docforge.cli.mcp_utils.json similarity index 100% rename from mcp/doc-forge/modules/docforge.cli.mcp_utils.json rename to doc-forge/mcp/modules/docforge.cli.mcp_utils.json diff --git a/mcp/doc-forge/modules/docforge.cli.mkdocs_utils.json b/doc-forge/mcp/modules/docforge.cli.mkdocs_utils.json similarity index 100% rename from mcp/doc-forge/modules/docforge.cli.mkdocs_utils.json rename to doc-forge/mcp/modules/docforge.cli.mkdocs_utils.json diff --git a/mcp/doc-forge/modules/docforge.json b/doc-forge/mcp/modules/docforge.json similarity index 100% rename from mcp/doc-forge/modules/docforge.json rename to doc-forge/mcp/modules/docforge.json diff --git a/mcp/doc-forge/modules/docforge.loaders.griffe_loader.json b/doc-forge/mcp/modules/docforge.loaders.griffe_loader.json similarity index 100% rename from mcp/doc-forge/modules/docforge.loaders.griffe_loader.json rename to doc-forge/mcp/modules/docforge.loaders.griffe_loader.json diff --git a/mcp/doc-forge/modules/docforge.loaders.json b/doc-forge/mcp/modules/docforge.loaders.json similarity index 100% rename from mcp/doc-forge/modules/docforge.loaders.json rename to doc-forge/mcp/modules/docforge.loaders.json diff --git a/mcp/doc-forge/modules/docforge.models.json b/doc-forge/mcp/modules/docforge.models.json similarity index 100% rename from mcp/doc-forge/modules/docforge.models.json rename to doc-forge/mcp/modules/docforge.models.json diff --git a/mcp/doc-forge/modules/docforge.models.module.json b/doc-forge/mcp/modules/docforge.models.module.json similarity index 100% rename from mcp/doc-forge/modules/docforge.models.module.json rename to doc-forge/mcp/modules/docforge.models.module.json diff --git a/mcp/doc-forge/modules/docforge.models.object.json b/doc-forge/mcp/modules/docforge.models.object.json similarity index 100% rename from mcp/doc-forge/modules/docforge.models.object.json rename to doc-forge/mcp/modules/docforge.models.object.json diff --git a/mcp/doc-forge/modules/docforge.models.project.json b/doc-forge/mcp/modules/docforge.models.project.json similarity index 100% rename from mcp/doc-forge/modules/docforge.models.project.json rename to doc-forge/mcp/modules/docforge.models.project.json diff --git a/mcp/doc-forge/modules/docforge.nav.json b/doc-forge/mcp/modules/docforge.nav.json similarity index 100% rename from mcp/doc-forge/modules/docforge.nav.json rename to doc-forge/mcp/modules/docforge.nav.json diff --git a/mcp/doc-forge/modules/docforge.nav.mkdocs.json b/doc-forge/mcp/modules/docforge.nav.mkdocs.json similarity index 100% rename from mcp/doc-forge/modules/docforge.nav.mkdocs.json rename to doc-forge/mcp/modules/docforge.nav.mkdocs.json diff --git a/mcp/doc-forge/modules/docforge.nav.resolver.json b/doc-forge/mcp/modules/docforge.nav.resolver.json similarity index 100% rename from mcp/doc-forge/modules/docforge.nav.resolver.json rename to doc-forge/mcp/modules/docforge.nav.resolver.json diff --git a/mcp/doc-forge/modules/docforge.nav.spec.json b/doc-forge/mcp/modules/docforge.nav.spec.json similarity index 100% rename from mcp/doc-forge/modules/docforge.nav.spec.json rename to doc-forge/mcp/modules/docforge.nav.spec.json diff --git a/mcp/doc-forge/modules/docforge.nav.wiki.json b/doc-forge/mcp/modules/docforge.nav.wiki.json similarity index 100% rename from mcp/doc-forge/modules/docforge.nav.wiki.json rename to doc-forge/mcp/modules/docforge.nav.wiki.json diff --git a/mcp/doc-forge/modules/docforge.renderers.base.json b/doc-forge/mcp/modules/docforge.renderers.base.json similarity index 100% rename from mcp/doc-forge/modules/docforge.renderers.base.json rename to doc-forge/mcp/modules/docforge.renderers.base.json diff --git a/mcp/doc-forge/modules/docforge.renderers.json b/doc-forge/mcp/modules/docforge.renderers.json similarity index 100% rename from mcp/doc-forge/modules/docforge.renderers.json rename to doc-forge/mcp/modules/docforge.renderers.json diff --git a/mcp/doc-forge/modules/docforge.renderers.mcp_renderer.json b/doc-forge/mcp/modules/docforge.renderers.mcp_renderer.json similarity index 100% rename from mcp/doc-forge/modules/docforge.renderers.mcp_renderer.json rename to doc-forge/mcp/modules/docforge.renderers.mcp_renderer.json diff --git a/mcp/doc-forge/modules/docforge.renderers.mkdocs_renderer.json b/doc-forge/mcp/modules/docforge.renderers.mkdocs_renderer.json similarity index 100% rename from mcp/doc-forge/modules/docforge.renderers.mkdocs_renderer.json rename to doc-forge/mcp/modules/docforge.renderers.mkdocs_renderer.json diff --git a/mcp/doc-forge/modules/docforge.servers.json b/doc-forge/mcp/modules/docforge.servers.json similarity index 100% rename from mcp/doc-forge/modules/docforge.servers.json rename to doc-forge/mcp/modules/docforge.servers.json diff --git a/mcp/doc-forge/modules/docforge.servers.mcp_server.json b/doc-forge/mcp/modules/docforge.servers.mcp_server.json similarity index 100% rename from mcp/doc-forge/modules/docforge.servers.mcp_server.json rename to doc-forge/mcp/modules/docforge.servers.mcp_server.json diff --git a/mcp/doc-forge/nav.json b/doc-forge/mcp/nav.json similarity index 100% rename from mcp/doc-forge/nav.json rename to doc-forge/mcp/nav.json diff --git a/mcp/hexa/index.json b/hexa/mcp/index.json similarity index 100% rename from mcp/hexa/index.json rename to hexa/mcp/index.json diff --git a/mcp/hexa/modules/hexa.check_matches.json b/hexa/mcp/modules/hexa.check_matches.json similarity index 100% rename from mcp/hexa/modules/hexa.check_matches.json rename to hexa/mcp/modules/hexa.check_matches.json diff --git a/mcp/hexa/modules/hexa.cli.json b/hexa/mcp/modules/hexa.cli.json similarity index 100% rename from mcp/hexa/modules/hexa.cli.json rename to hexa/mcp/modules/hexa.cli.json diff --git a/mcp/hexa/modules/hexa.container.json b/hexa/mcp/modules/hexa.container.json similarity index 100% rename from mcp/hexa/modules/hexa.container.json rename to hexa/mcp/modules/hexa.container.json diff --git a/mcp/hexa/modules/hexa.generate_abc.json b/hexa/mcp/modules/hexa.generate_abc.json similarity index 100% rename from mcp/hexa/modules/hexa.generate_abc.json rename to hexa/mcp/modules/hexa.generate_abc.json diff --git a/mcp/hexa/modules/hexa.generate_yaml.json b/hexa/mcp/modules/hexa.generate_yaml.json similarity index 100% rename from mcp/hexa/modules/hexa.generate_yaml.json rename to hexa/mcp/modules/hexa.generate_yaml.json diff --git a/mcp/hexa/modules/hexa.json b/hexa/mcp/modules/hexa.json similarity index 100% rename from mcp/hexa/modules/hexa.json rename to hexa/mcp/modules/hexa.json diff --git a/mcp/hexa/modules/hexa.model.json b/hexa/mcp/modules/hexa.model.json similarity index 100% rename from mcp/hexa/modules/hexa.model.json rename to hexa/mcp/modules/hexa.model.json diff --git a/mcp/hexa/modules/hexa.parse_abc.json b/hexa/mcp/modules/hexa.parse_abc.json similarity index 100% rename from mcp/hexa/modules/hexa.parse_abc.json rename to hexa/mcp/modules/hexa.parse_abc.json diff --git a/mcp/hexa/modules/hexa.parse_yaml.json b/hexa/mcp/modules/hexa.parse_yaml.json similarity index 100% rename from mcp/hexa/modules/hexa.parse_yaml.json rename to hexa/mcp/modules/hexa.parse_yaml.json diff --git a/mcp/hexa/nav.json b/hexa/mcp/nav.json similarity index 100% rename from mcp/hexa/nav.json rename to hexa/mcp/nav.json diff --git a/mcp/mail-intake/index.json b/mail-intake/mcp/index.json similarity index 100% rename from mcp/mail-intake/index.json rename to mail-intake/mcp/index.json diff --git a/mcp/mail-intake/modules/mail_intake.adapters.base.json b/mail-intake/mcp/modules/mail_intake.adapters.base.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.adapters.base.json rename to mail-intake/mcp/modules/mail_intake.adapters.base.json diff --git a/mcp/mail-intake/modules/mail_intake.adapters.gmail.json b/mail-intake/mcp/modules/mail_intake.adapters.gmail.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.adapters.gmail.json rename to mail-intake/mcp/modules/mail_intake.adapters.gmail.json diff --git a/mcp/mail-intake/modules/mail_intake.adapters.json b/mail-intake/mcp/modules/mail_intake.adapters.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.adapters.json rename to mail-intake/mcp/modules/mail_intake.adapters.json diff --git a/mcp/mail-intake/modules/mail_intake.auth.base.json b/mail-intake/mcp/modules/mail_intake.auth.base.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.auth.base.json rename to mail-intake/mcp/modules/mail_intake.auth.base.json diff --git a/mcp/mail-intake/modules/mail_intake.auth.google.json b/mail-intake/mcp/modules/mail_intake.auth.google.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.auth.google.json rename to mail-intake/mcp/modules/mail_intake.auth.google.json diff --git a/mcp/mail-intake/modules/mail_intake.auth.json b/mail-intake/mcp/modules/mail_intake.auth.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.auth.json rename to mail-intake/mcp/modules/mail_intake.auth.json diff --git a/mcp/mail-intake/modules/mail_intake.config.json b/mail-intake/mcp/modules/mail_intake.config.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.config.json rename to mail-intake/mcp/modules/mail_intake.config.json diff --git a/mcp/mail-intake/modules/mail_intake.credentials.json b/mail-intake/mcp/modules/mail_intake.credentials.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.credentials.json rename to mail-intake/mcp/modules/mail_intake.credentials.json diff --git a/mcp/mail-intake/modules/mail_intake.credentials.pickle.json b/mail-intake/mcp/modules/mail_intake.credentials.pickle.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.credentials.pickle.json rename to mail-intake/mcp/modules/mail_intake.credentials.pickle.json diff --git a/mcp/mail-intake/modules/mail_intake.credentials.redis.json b/mail-intake/mcp/modules/mail_intake.credentials.redis.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.credentials.redis.json rename to mail-intake/mcp/modules/mail_intake.credentials.redis.json diff --git a/mcp/mail-intake/modules/mail_intake.credentials.store.json b/mail-intake/mcp/modules/mail_intake.credentials.store.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.credentials.store.json rename to mail-intake/mcp/modules/mail_intake.credentials.store.json diff --git a/mcp/mail-intake/modules/mail_intake.exceptions.json b/mail-intake/mcp/modules/mail_intake.exceptions.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.exceptions.json rename to mail-intake/mcp/modules/mail_intake.exceptions.json diff --git a/mcp/mail-intake/modules/mail_intake.ingestion.json b/mail-intake/mcp/modules/mail_intake.ingestion.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.ingestion.json rename to mail-intake/mcp/modules/mail_intake.ingestion.json diff --git a/mcp/mail-intake/modules/mail_intake.ingestion.reader.json b/mail-intake/mcp/modules/mail_intake.ingestion.reader.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.ingestion.reader.json rename to mail-intake/mcp/modules/mail_intake.ingestion.reader.json diff --git a/mcp/mail-intake/modules/mail_intake.json b/mail-intake/mcp/modules/mail_intake.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.json rename to mail-intake/mcp/modules/mail_intake.json diff --git a/mcp/mail-intake/modules/mail_intake.models.json b/mail-intake/mcp/modules/mail_intake.models.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.models.json rename to mail-intake/mcp/modules/mail_intake.models.json diff --git a/mcp/mail-intake/modules/mail_intake.models.message.json b/mail-intake/mcp/modules/mail_intake.models.message.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.models.message.json rename to mail-intake/mcp/modules/mail_intake.models.message.json diff --git a/mcp/mail-intake/modules/mail_intake.models.thread.json b/mail-intake/mcp/modules/mail_intake.models.thread.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.models.thread.json rename to mail-intake/mcp/modules/mail_intake.models.thread.json diff --git a/mcp/mail-intake/modules/mail_intake.parsers.body.json b/mail-intake/mcp/modules/mail_intake.parsers.body.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.parsers.body.json rename to mail-intake/mcp/modules/mail_intake.parsers.body.json diff --git a/mcp/mail-intake/modules/mail_intake.parsers.headers.json b/mail-intake/mcp/modules/mail_intake.parsers.headers.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.parsers.headers.json rename to mail-intake/mcp/modules/mail_intake.parsers.headers.json diff --git a/mcp/mail-intake/modules/mail_intake.parsers.json b/mail-intake/mcp/modules/mail_intake.parsers.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.parsers.json rename to mail-intake/mcp/modules/mail_intake.parsers.json diff --git a/mcp/mail-intake/modules/mail_intake.parsers.subject.json b/mail-intake/mcp/modules/mail_intake.parsers.subject.json similarity index 100% rename from mcp/mail-intake/modules/mail_intake.parsers.subject.json rename to mail-intake/mcp/modules/mail_intake.parsers.subject.json diff --git a/mcp/mail-intake/nav.json b/mail-intake/mcp/nav.json similarity index 100% rename from mcp/mail-intake/nav.json rename to mail-intake/mcp/nav.json diff --git a/main.py b/main.py index 8cf99c8..44e4b95 100644 --- a/main.py +++ b/main.py @@ -15,7 +15,7 @@ from http.server import BaseHTTPRequestHandler, HTTPServer from pathlib import Path from config import MCPBundle, load_config -from core import MCPServer +from mcp_server import MCPServer from registry import StandardsMCPServer APP_ROOT = Path(__file__).resolve().parent diff --git a/mcp/standards/libraries.json b/mcp/standards/libraries.json deleted file mode 100644 index 044e040..0000000 --- a/mcp/standards/libraries.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "project": "standards", - "note": "Machine-readable library registry. Mirrors standards_src/wiki/13_library_registry.md. Query with the find_library MCP tool.", - "libraries": [ - { - "name": "DAG Pipe", - "import": "dagpipe", - "purpose": "Deterministic state-transformation DAG engine.", - "use_instead_of": "hand-rolled orchestration, topological ordering, immutable state propagation", - "capabilities": ["pipeline", "orchestration", "dag", "graph", "engine", "state", "node"], - "mcp": { "server": "dagpipe", "port": 8006 } - }, - { - "name": "Hexa", - "import": "hexa", - "purpose": "Declarative dependency injection and composition-root tooling.", - "use_instead_of": "manual wiring, hand-written factories, manual composition roots", - "capabilities": ["di", "dependency-injection", "composition", "wiring", "ports"], - "mcp": { "server": "hexa", "port": null, "note": "bundle exists; port not yet assigned" } - }, - { - "name": "Mongo Ops", - "import": "mongo_ops", - "purpose": "Async MongoDB repositories, caching, population and transactions.", - "use_instead_of": "raw Motor CRUD, connection lifecycle, generic repository code", - "capabilities": ["mongo", "mongodb", "database", "repository", "crud", "cache", "transactions"], - "mcp": { "server": "mongo_ops", "port": 8007 } - }, - { - "name": "Omniread", - "import": "omniread", - "purpose": "Format-agnostic content acquisition and parsing (HTML, PDF, CSV, XLSX).", - "use_instead_of": "custom scrapers and parsers for HTML/PDF/CSV/XLSX", - "capabilities": ["ingestion", "parse", "pdf", "csv", "xlsx", "html", "scrape", "fetch"], - "mcp": { "server": "omniread", "port": 8003 } - }, - { - "name": "OpenAPI First", - "import": "openapi_first", - "purpose": "Spec-first FastAPI bootstrap, client, and codegen.", - "use_instead_of": "decorator routers and hand-written API clients", - "capabilities": ["openapi", "http", "api", "routing", "fastapi", "client", "codegen", "spec"], - "mcp": { "server": "openapi_first", "port": 8004 } - }, - { - "name": "Mail Intake", - "import": "mail_intake", - "purpose": "Provider-agnostic read-only email ingestion.", - "use_instead_of": "Gmail OAuth and MIME parsing implemented by hand", - "capabilities": ["email", "mail", "gmail", "ingestion", "imap", "mime", "oauth"], - "mcp": { "server": "mail_intake", "port": 8002 } - }, - { - "name": "Py JWT", - "import": "jwtlib", - "purpose": "JWT authentication primitives (register, login, introspect).", - "use_instead_of": "password hashing and token issuance/verification written by hand", - "capabilities": ["auth", "jwt", "token", "login", "password", "introspect", "security"], - "mcp": { "server": "jwtlib", "port": 8005 } - }, - { - "name": "Doc Forge", - "import": "docforge", - "purpose": "Docstring compiler that renders documentation for humans (MkDocs) and machines (MCP).", - "use_instead_of": "custom documentation generators", - "capabilities": ["docs", "documentation", "mkdocs", "mcp", "docstrings", "gsdfc"], - "mcp": { "server": "docforge", "port": 8001 } - }, - { - "name": "Auth Server", - "import": "auth-server", - "purpose": "Central identity service (register/login/me/introspect).", - "use_instead_of": "building authentication endpoints yourself", - "capabilities": ["auth", "identity", "service", "register", "login", "introspect"], - "mcp": { "server": null, "port": null, "note": "service; no MCP bundle" } - } - ] -} diff --git a/core.py b/mcp_server.py similarity index 100% rename from core.py rename to mcp_server.py diff --git a/mcp/mongo-ops/index.json b/mongo-ops/mcp/index.json similarity index 100% rename from mcp/mongo-ops/index.json rename to mongo-ops/mcp/index.json diff --git a/mcp/mongo-ops/modules/mongo_ops.cache.backend.json b/mongo-ops/mcp/modules/mongo_ops.cache.backend.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.cache.backend.json rename to mongo-ops/mcp/modules/mongo_ops.cache.backend.json diff --git a/mcp/mongo-ops/modules/mongo_ops.cache.config.json b/mongo-ops/mcp/modules/mongo_ops.cache.config.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.cache.config.json rename to mongo-ops/mcp/modules/mongo_ops.cache.config.json diff --git a/mcp/mongo-ops/modules/mongo_ops.cache.in_memory.json b/mongo-ops/mcp/modules/mongo_ops.cache.in_memory.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.cache.in_memory.json rename to mongo-ops/mcp/modules/mongo_ops.cache.in_memory.json diff --git a/mcp/mongo-ops/modules/mongo_ops.cache.json b/mongo-ops/mcp/modules/mongo_ops.cache.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.cache.json rename to mongo-ops/mcp/modules/mongo_ops.cache.json diff --git a/mcp/mongo-ops/modules/mongo_ops.cache.redis_backend.json b/mongo-ops/mcp/modules/mongo_ops.cache.redis_backend.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.cache.redis_backend.json rename to mongo-ops/mcp/modules/mongo_ops.cache.redis_backend.json diff --git a/mcp/mongo-ops/modules/mongo_ops.cache.repository.json b/mongo-ops/mcp/modules/mongo_ops.cache.repository.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.cache.repository.json rename to mongo-ops/mcp/modules/mongo_ops.cache.repository.json diff --git a/mcp/mongo-ops/modules/mongo_ops.connection.json b/mongo-ops/mcp/modules/mongo_ops.connection.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.connection.json rename to mongo-ops/mcp/modules/mongo_ops.connection.json diff --git a/mcp/mongo-ops/modules/mongo_ops.json b/mongo-ops/mcp/modules/mongo_ops.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.json rename to mongo-ops/mcp/modules/mongo_ops.json diff --git a/mcp/mongo-ops/modules/mongo_ops.models.json b/mongo-ops/mcp/modules/mongo_ops.models.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.models.json rename to mongo-ops/mcp/modules/mongo_ops.models.json diff --git a/mcp/mongo-ops/modules/mongo_ops.populate.engine.json b/mongo-ops/mcp/modules/mongo_ops.populate.engine.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.populate.engine.json rename to mongo-ops/mcp/modules/mongo_ops.populate.engine.json diff --git a/mcp/mongo-ops/modules/mongo_ops.populate.json b/mongo-ops/mcp/modules/mongo_ops.populate.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.populate.json rename to mongo-ops/mcp/modules/mongo_ops.populate.json diff --git a/mcp/mongo-ops/modules/mongo_ops.populate.rules.json b/mongo-ops/mcp/modules/mongo_ops.populate.rules.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.populate.rules.json rename to mongo-ops/mcp/modules/mongo_ops.populate.rules.json diff --git a/mcp/mongo-ops/modules/mongo_ops.registry.json b/mongo-ops/mcp/modules/mongo_ops.registry.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.registry.json rename to mongo-ops/mcp/modules/mongo_ops.registry.json diff --git a/mcp/mongo-ops/modules/mongo_ops.repository.json b/mongo-ops/mcp/modules/mongo_ops.repository.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.repository.json rename to mongo-ops/mcp/modules/mongo_ops.repository.json diff --git a/mcp/mongo-ops/modules/mongo_ops.transactions.json b/mongo-ops/mcp/modules/mongo_ops.transactions.json similarity index 100% rename from mcp/mongo-ops/modules/mongo_ops.transactions.json rename to mongo-ops/mcp/modules/mongo_ops.transactions.json diff --git a/mcp/mongo-ops/nav.json b/mongo-ops/mcp/nav.json similarity index 100% rename from mcp/mongo-ops/nav.json rename to mongo-ops/mcp/nav.json diff --git a/nginx.conf b/nginx.conf index 1488814..9cbfe1c 100644 --- a/nginx.conf +++ b/nginx.conf @@ -5,6 +5,10 @@ server { root /usr/share/nginx/html; index index.html lib/index.html api/index.html; + location ~ ^/[^/]+/mcp/ { + deny all; + } + location / { try_files $uri $uri/ /index.html; } diff --git a/mcp/omniread/index.json b/omniread/mcp/index.json similarity index 100% rename from mcp/omniread/index.json rename to omniread/mcp/index.json diff --git a/mcp/omniread/modules/omniread.core.content.json b/omniread/mcp/modules/omniread.core.content.json similarity index 100% rename from mcp/omniread/modules/omniread.core.content.json rename to omniread/mcp/modules/omniread.core.content.json diff --git a/mcp/omniread/modules/omniread.core.json b/omniread/mcp/modules/omniread.core.json similarity index 100% rename from mcp/omniread/modules/omniread.core.json rename to omniread/mcp/modules/omniread.core.json diff --git a/mcp/omniread/modules/omniread.core.parser.json b/omniread/mcp/modules/omniread.core.parser.json similarity index 100% rename from mcp/omniread/modules/omniread.core.parser.json rename to omniread/mcp/modules/omniread.core.parser.json diff --git a/mcp/omniread/modules/omniread.core.scraper.json b/omniread/mcp/modules/omniread.core.scraper.json similarity index 100% rename from mcp/omniread/modules/omniread.core.scraper.json rename to omniread/mcp/modules/omniread.core.scraper.json diff --git a/mcp/omniread/modules/omniread.csv.client.json b/omniread/mcp/modules/omniread.csv.client.json similarity index 100% rename from mcp/omniread/modules/omniread.csv.client.json rename to omniread/mcp/modules/omniread.csv.client.json diff --git a/mcp/omniread/modules/omniread.csv.json b/omniread/mcp/modules/omniread.csv.json similarity index 100% rename from mcp/omniread/modules/omniread.csv.json rename to omniread/mcp/modules/omniread.csv.json diff --git a/mcp/omniread/modules/omniread.csv.parser.json b/omniread/mcp/modules/omniread.csv.parser.json similarity index 100% rename from mcp/omniread/modules/omniread.csv.parser.json rename to omniread/mcp/modules/omniread.csv.parser.json diff --git a/mcp/omniread/modules/omniread.csv.parser_base.json b/omniread/mcp/modules/omniread.csv.parser_base.json similarity index 100% rename from mcp/omniread/modules/omniread.csv.parser_base.json rename to omniread/mcp/modules/omniread.csv.parser_base.json diff --git a/mcp/omniread/modules/omniread.csv.scraper.json b/omniread/mcp/modules/omniread.csv.scraper.json similarity index 100% rename from mcp/omniread/modules/omniread.csv.scraper.json rename to omniread/mcp/modules/omniread.csv.scraper.json diff --git a/mcp/omniread/modules/omniread.html.json b/omniread/mcp/modules/omniread.html.json similarity index 100% rename from mcp/omniread/modules/omniread.html.json rename to omniread/mcp/modules/omniread.html.json diff --git a/mcp/omniread/modules/omniread.html.parser.json b/omniread/mcp/modules/omniread.html.parser.json similarity index 100% rename from mcp/omniread/modules/omniread.html.parser.json rename to omniread/mcp/modules/omniread.html.parser.json diff --git a/mcp/omniread/modules/omniread.html.scraper.json b/omniread/mcp/modules/omniread.html.scraper.json similarity index 100% rename from mcp/omniread/modules/omniread.html.scraper.json rename to omniread/mcp/modules/omniread.html.scraper.json diff --git a/mcp/omniread/modules/omniread.json b/omniread/mcp/modules/omniread.json similarity index 100% rename from mcp/omniread/modules/omniread.json rename to omniread/mcp/modules/omniread.json diff --git a/mcp/omniread/modules/omniread.pdf.client.json b/omniread/mcp/modules/omniread.pdf.client.json similarity index 100% rename from mcp/omniread/modules/omniread.pdf.client.json rename to omniread/mcp/modules/omniread.pdf.client.json diff --git a/mcp/omniread/modules/omniread.pdf.json b/omniread/mcp/modules/omniread.pdf.json similarity index 100% rename from mcp/omniread/modules/omniread.pdf.json rename to omniread/mcp/modules/omniread.pdf.json diff --git a/mcp/omniread/modules/omniread.pdf.parser.json b/omniread/mcp/modules/omniread.pdf.parser.json similarity index 100% rename from mcp/omniread/modules/omniread.pdf.parser.json rename to omniread/mcp/modules/omniread.pdf.parser.json diff --git a/mcp/omniread/modules/omniread.pdf.scraper.json b/omniread/mcp/modules/omniread.pdf.scraper.json similarity index 100% rename from mcp/omniread/modules/omniread.pdf.scraper.json rename to omniread/mcp/modules/omniread.pdf.scraper.json diff --git a/mcp/omniread/modules/omniread.xlsx.client.json b/omniread/mcp/modules/omniread.xlsx.client.json similarity index 100% rename from mcp/omniread/modules/omniread.xlsx.client.json rename to omniread/mcp/modules/omniread.xlsx.client.json diff --git a/mcp/omniread/modules/omniread.xlsx.json b/omniread/mcp/modules/omniread.xlsx.json similarity index 100% rename from mcp/omniread/modules/omniread.xlsx.json rename to omniread/mcp/modules/omniread.xlsx.json diff --git a/mcp/omniread/modules/omniread.xlsx.parser.json b/omniread/mcp/modules/omniread.xlsx.parser.json similarity index 100% rename from mcp/omniread/modules/omniread.xlsx.parser.json rename to omniread/mcp/modules/omniread.xlsx.parser.json diff --git a/mcp/omniread/modules/omniread.xlsx.parser_base.json b/omniread/mcp/modules/omniread.xlsx.parser_base.json similarity index 100% rename from mcp/omniread/modules/omniread.xlsx.parser_base.json rename to omniread/mcp/modules/omniread.xlsx.parser_base.json diff --git a/mcp/omniread/modules/omniread.xlsx.scraper.json b/omniread/mcp/modules/omniread.xlsx.scraper.json similarity index 100% rename from mcp/omniread/modules/omniread.xlsx.scraper.json rename to omniread/mcp/modules/omniread.xlsx.scraper.json diff --git a/mcp/omniread/nav.json b/omniread/mcp/nav.json similarity index 100% rename from mcp/omniread/nav.json rename to omniread/mcp/nav.json diff --git a/mcp/openapi-first/index.json b/openapi-first/mcp/index.json similarity index 100% rename from mcp/openapi-first/index.json rename to openapi-first/mcp/index.json diff --git a/mcp/openapi-first/modules/openapi_first.app.json b/openapi-first/mcp/modules/openapi_first.app.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.app.json rename to openapi-first/mcp/modules/openapi_first.app.json diff --git a/mcp/openapi-first/modules/openapi_first.binder.json b/openapi-first/mcp/modules/openapi_first.binder.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.binder.json rename to openapi-first/mcp/modules/openapi_first.binder.json diff --git a/mcp/openapi-first/modules/openapi_first.cli.json b/openapi-first/mcp/modules/openapi_first.cli.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.cli.json rename to openapi-first/mcp/modules/openapi_first.cli.json diff --git a/mcp/openapi-first/modules/openapi_first.client.json b/openapi-first/mcp/modules/openapi_first.client.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.client.json rename to openapi-first/mcp/modules/openapi_first.client.json diff --git a/mcp/openapi-first/modules/openapi_first.codegen.json b/openapi-first/mcp/modules/openapi_first.codegen.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.codegen.json rename to openapi-first/mcp/modules/openapi_first.codegen.json diff --git a/mcp/openapi-first/modules/openapi_first.codegen_routes.json b/openapi-first/mcp/modules/openapi_first.codegen_routes.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.codegen_routes.json rename to openapi-first/mcp/modules/openapi_first.codegen_routes.json diff --git a/mcp/openapi-first/modules/openapi_first.errors.json b/openapi-first/mcp/modules/openapi_first.errors.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.errors.json rename to openapi-first/mcp/modules/openapi_first.errors.json diff --git a/mcp/openapi-first/modules/openapi_first.json b/openapi-first/mcp/modules/openapi_first.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.json rename to openapi-first/mcp/modules/openapi_first.json diff --git a/mcp/openapi-first/modules/openapi_first.loader.json b/openapi-first/mcp/modules/openapi_first.loader.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.loader.json rename to openapi-first/mcp/modules/openapi_first.loader.json diff --git a/mcp/openapi-first/modules/openapi_first.security.json b/openapi-first/mcp/modules/openapi_first.security.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.security.json rename to openapi-first/mcp/modules/openapi_first.security.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.crud_app.data.json b/openapi-first/mcp/modules/openapi_first.templates.crud_app.data.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.crud_app.data.json rename to openapi-first/mcp/modules/openapi_first.templates.crud_app.data.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.crud_app.json b/openapi-first/mcp/modules/openapi_first.templates.crud_app.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.crud_app.json rename to openapi-first/mcp/modules/openapi_first.templates.crud_app.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.crud_app.main.json b/openapi-first/mcp/modules/openapi_first.templates.crud_app.main.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.crud_app.main.json rename to openapi-first/mcp/modules/openapi_first.templates.crud_app.main.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.crud_app.routes.json b/openapi-first/mcp/modules/openapi_first.templates.crud_app.routes.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.crud_app.routes.json rename to openapi-first/mcp/modules/openapi_first.templates.crud_app.routes.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.crud_app.test_crud_app.json b/openapi-first/mcp/modules/openapi_first.templates.crud_app.test_crud_app.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.crud_app.test_crud_app.json rename to openapi-first/mcp/modules/openapi_first.templates.crud_app.test_crud_app.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.health_app.json b/openapi-first/mcp/modules/openapi_first.templates.health_app.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.health_app.json rename to openapi-first/mcp/modules/openapi_first.templates.health_app.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.health_app.main.json b/openapi-first/mcp/modules/openapi_first.templates.health_app.main.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.health_app.main.json rename to openapi-first/mcp/modules/openapi_first.templates.health_app.main.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.health_app.routes.json b/openapi-first/mcp/modules/openapi_first.templates.health_app.routes.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.health_app.routes.json rename to openapi-first/mcp/modules/openapi_first.templates.health_app.routes.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.json b/openapi-first/mcp/modules/openapi_first.templates.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.json rename to openapi-first/mcp/modules/openapi_first.templates.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.model_app.data.json b/openapi-first/mcp/modules/openapi_first.templates.model_app.data.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.model_app.data.json rename to openapi-first/mcp/modules/openapi_first.templates.model_app.data.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.model_app.json b/openapi-first/mcp/modules/openapi_first.templates.model_app.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.model_app.json rename to openapi-first/mcp/modules/openapi_first.templates.model_app.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.model_app.main.json b/openapi-first/mcp/modules/openapi_first.templates.model_app.main.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.model_app.main.json rename to openapi-first/mcp/modules/openapi_first.templates.model_app.main.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.model_app.models.json b/openapi-first/mcp/modules/openapi_first.templates.model_app.models.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.model_app.models.json rename to openapi-first/mcp/modules/openapi_first.templates.model_app.models.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.model_app.routes.json b/openapi-first/mcp/modules/openapi_first.templates.model_app.routes.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.model_app.routes.json rename to openapi-first/mcp/modules/openapi_first.templates.model_app.routes.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.model_app.test_model_app.json b/openapi-first/mcp/modules/openapi_first.templates.model_app.test_model_app.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.model_app.test_model_app.json rename to openapi-first/mcp/modules/openapi_first.templates.model_app.test_model_app.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.vet_app.data.json b/openapi-first/mcp/modules/openapi_first.templates.vet_app.data.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.vet_app.data.json rename to openapi-first/mcp/modules/openapi_first.templates.vet_app.data.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.vet_app.json b/openapi-first/mcp/modules/openapi_first.templates.vet_app.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.vet_app.json rename to openapi-first/mcp/modules/openapi_first.templates.vet_app.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.vet_app.main.json b/openapi-first/mcp/modules/openapi_first.templates.vet_app.main.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.vet_app.main.json rename to openapi-first/mcp/modules/openapi_first.templates.vet_app.main.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.vet_app.models.json b/openapi-first/mcp/modules/openapi_first.templates.vet_app.models.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.vet_app.models.json rename to openapi-first/mcp/modules/openapi_first.templates.vet_app.models.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.vet_app.routes.json b/openapi-first/mcp/modules/openapi_first.templates.vet_app.routes.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.vet_app.routes.json rename to openapi-first/mcp/modules/openapi_first.templates.vet_app.routes.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.vet_app.sse.json b/openapi-first/mcp/modules/openapi_first.templates.vet_app.sse.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.vet_app.sse.json rename to openapi-first/mcp/modules/openapi_first.templates.vet_app.sse.json diff --git a/mcp/openapi-first/modules/openapi_first.templates.vet_app.test_vet_app.json b/openapi-first/mcp/modules/openapi_first.templates.vet_app.test_vet_app.json similarity index 100% rename from mcp/openapi-first/modules/openapi_first.templates.vet_app.test_vet_app.json rename to openapi-first/mcp/modules/openapi_first.templates.vet_app.test_vet_app.json diff --git a/mcp/openapi-first/nav.json b/openapi-first/mcp/nav.json similarity index 100% rename from mcp/openapi-first/nav.json rename to openapi-first/mcp/nav.json diff --git a/mcp/py-jwt/index.json b/py-jwt/mcp/index.json similarity index 100% rename from mcp/py-jwt/index.json rename to py-jwt/mcp/index.json diff --git a/mcp/py-jwt/modules/jwtlib.app.json b/py-jwt/mcp/modules/jwtlib.app.json similarity index 100% rename from mcp/py-jwt/modules/jwtlib.app.json rename to py-jwt/mcp/modules/jwtlib.app.json diff --git a/mcp/py-jwt/modules/jwtlib.exceptions.json b/py-jwt/mcp/modules/jwtlib.exceptions.json similarity index 100% rename from mcp/py-jwt/modules/jwtlib.exceptions.json rename to py-jwt/mcp/modules/jwtlib.exceptions.json diff --git a/mcp/py-jwt/modules/jwtlib.introspection.json b/py-jwt/mcp/modules/jwtlib.introspection.json similarity index 100% rename from mcp/py-jwt/modules/jwtlib.introspection.json rename to py-jwt/mcp/modules/jwtlib.introspection.json diff --git a/mcp/py-jwt/modules/jwtlib.json b/py-jwt/mcp/modules/jwtlib.json similarity index 100% rename from mcp/py-jwt/modules/jwtlib.json rename to py-jwt/mcp/modules/jwtlib.json diff --git a/mcp/py-jwt/modules/jwtlib.models.app.json b/py-jwt/mcp/modules/jwtlib.models.app.json similarity index 100% rename from mcp/py-jwt/modules/jwtlib.models.app.json rename to py-jwt/mcp/modules/jwtlib.models.app.json diff --git a/mcp/py-jwt/modules/jwtlib.models.common.json b/py-jwt/mcp/modules/jwtlib.models.common.json similarity index 100% rename from mcp/py-jwt/modules/jwtlib.models.common.json rename to py-jwt/mcp/modules/jwtlib.models.common.json diff --git a/mcp/py-jwt/modules/jwtlib.models.json b/py-jwt/mcp/modules/jwtlib.models.json similarity index 100% rename from mcp/py-jwt/modules/jwtlib.models.json rename to py-jwt/mcp/modules/jwtlib.models.json diff --git a/mcp/py-jwt/modules/jwtlib.models.mongo.json b/py-jwt/mcp/modules/jwtlib.models.mongo.json similarity index 100% rename from mcp/py-jwt/modules/jwtlib.models.mongo.json rename to py-jwt/mcp/modules/jwtlib.models.mongo.json diff --git a/mcp/py-jwt/modules/jwtlib.models.security.json b/py-jwt/mcp/modules/jwtlib.models.security.json similarity index 100% rename from mcp/py-jwt/modules/jwtlib.models.security.json rename to py-jwt/mcp/modules/jwtlib.models.security.json diff --git a/mcp/py-jwt/modules/jwtlib.repository.json b/py-jwt/mcp/modules/jwtlib.repository.json similarity index 100% rename from mcp/py-jwt/modules/jwtlib.repository.json rename to py-jwt/mcp/modules/jwtlib.repository.json diff --git a/mcp/py-jwt/modules/jwtlib.security.json b/py-jwt/mcp/modules/jwtlib.security.json similarity index 100% rename from mcp/py-jwt/modules/jwtlib.security.json rename to py-jwt/mcp/modules/jwtlib.security.json diff --git a/mcp/py-jwt/modules/jwtlib.utils.json b/py-jwt/mcp/modules/jwtlib.utils.json similarity index 100% rename from mcp/py-jwt/modules/jwtlib.utils.json rename to py-jwt/mcp/modules/jwtlib.utils.json diff --git a/mcp/py-jwt/nav.json b/py-jwt/mcp/nav.json similarity index 100% rename from mcp/py-jwt/nav.json rename to py-jwt/mcp/nav.json diff --git a/registry.py b/registry.py index 6b6a8b4..2104b7c 100644 --- a/registry.py +++ b/registry.py @@ -19,7 +19,7 @@ from pathlib import Path from typing import Any from config import MCPBundle -from core import MCPServer +from mcp_server import MCPServer class StandardsMCPServer(MCPServer): diff --git a/mcp/standards/index.json b/standards/mcp/index.json similarity index 100% rename from mcp/standards/index.json rename to standards/mcp/index.json diff --git a/standards/mcp/libraries.json b/standards/mcp/libraries.json new file mode 100644 index 0000000000000000000000000000000000000000..facdfb06b3cbad84a179aab771d554dd27301cd2 GIT binary patch literal 7464 zcmb`M?Qa`J5XSd2692;~pIWKLl=3F{6cXBkuo4I_l~5HWXUB1gU$7lgtLncFJii@} z_wIZbTfHcX23YJU@@3w^%`lhD`a zT%QZ|JSohYXwFh|e0)#i@^BqSnllI;%^66-?8|VY@0mVF`aX~At<+}3P%<>l!zz3t zSx@b`ex~|esJ(5)xny%`>V`Xw{Y$^y@H9LN=au!(HLAM)SoWah=Wwe&bY^jtrR>gR z#dWmvN^7$3>WWx*6i(yFsVuzFT4kRUcR12o_zZ9Ux$zqwPrj#RF__3JW6f}H9*4v5 zLVc&QWftYh_i5Hhb7s+3DQ9a-ZLFVL%}H1_++k6sb3g++}GWE`hgr;2^v% z@Hy>ZEMLvk3vS;<%ZSlD{1ZPNpW7(2Ou{Z4i(iLN_4B3HcwfT*`-EqjWL9*gCR8Lw!-c+ldNPANx>$o-E%q3Sh&#h(aJJD28U#c}vfZO&{wVXP@56HIx9VVRqe=zy{51ac1Asldr%I5&lYD4d1gK0}8T?%hX5DmwFGIjV(Tg z3KB1u#}=*hk!6p%bg_l9U{$uz<^#Oa{_ITaR;Ek%|r6R~nU;V6l6q_C} zVm`Cz+q+Gwqj`xzt5r7K&8Zz8Nt#~z$f`uZUw$UBMI6ce)J|jzs`GXg4cO&gcBeIY zAI*euB=!P2RNL`R)k9X`&P`pm&>rc_CF`!=Rk$BicU!%$KMV`p!;WK%n75LxE=hiL zNpMewH@UQUNA|ky(wC0{h@5- z=8(6R)FMl=ryC)r zKGW>3bzHOKx9T;Qmwo5b>Urw&?X#dh=YRNJw)}$XZ=&{JhjL%_b+x<`UQ`*8{%2Qw QeXV;z^?d$1W_DxF|MQY(K>z>% literal 0 HcmV?d00001 diff --git a/mcp/standards/modules/composition_root.json b/standards/mcp/modules/composition_root.json similarity index 100% rename from mcp/standards/modules/composition_root.json rename to standards/mcp/modules/composition_root.json diff --git a/mcp/standards/modules/crud_template.json b/standards/mcp/modules/crud_template.json similarity index 100% rename from mcp/standards/modules/crud_template.json rename to standards/mcp/modules/crud_template.json diff --git a/mcp/standards/modules/genericity_matrix.json b/standards/mcp/modules/genericity_matrix.json similarity index 100% rename from mcp/standards/modules/genericity_matrix.json rename to standards/mcp/modules/genericity_matrix.json diff --git a/mcp/standards/modules/human_in_loop.json b/standards/mcp/modules/human_in_loop.json similarity index 100% rename from mcp/standards/modules/human_in_loop.json rename to standards/mcp/modules/human_in_loop.json diff --git a/mcp/standards/modules/index.json b/standards/mcp/modules/index.json similarity index 100% rename from mcp/standards/modules/index.json rename to standards/mcp/modules/index.json diff --git a/mcp/standards/modules/infra_adaptors.json b/standards/mcp/modules/infra_adaptors.json similarity index 100% rename from mcp/standards/modules/infra_adaptors.json rename to standards/mcp/modules/infra_adaptors.json diff --git a/mcp/standards/modules/layering_rules.json b/standards/mcp/modules/layering_rules.json similarity index 100% rename from mcp/standards/modules/layering_rules.json rename to standards/mcp/modules/layering_rules.json diff --git a/mcp/standards/modules/library_registry.json b/standards/mcp/modules/library_registry.json similarity index 100% rename from mcp/standards/modules/library_registry.json rename to standards/mcp/modules/library_registry.json diff --git a/mcp/standards/modules/pipeline_scaffold.json b/standards/mcp/modules/pipeline_scaffold.json similarity index 100% rename from mcp/standards/modules/pipeline_scaffold.json rename to standards/mcp/modules/pipeline_scaffold.json diff --git a/mcp/standards/modules/spec_first_routing.json b/standards/mcp/modules/spec_first_routing.json similarity index 100% rename from mcp/standards/modules/spec_first_routing.json rename to standards/mcp/modules/spec_first_routing.json diff --git a/mcp/standards/modules/worker_and_progress.json b/standards/mcp/modules/worker_and_progress.json similarity index 100% rename from mcp/standards/modules/worker_and_progress.json rename to standards/mcp/modules/worker_and_progress.json diff --git a/mcp/standards/nav.json b/standards/mcp/nav.json similarity index 100% rename from mcp/standards/nav.json rename to standards/mcp/nav.json diff --git a/standards/mcp/standards/index.json b/standards/mcp/standards/index.json new file mode 100644 index 0000000..b06d01e --- /dev/null +++ b/standards/mcp/standards/index.json @@ -0,0 +1,6 @@ +{ + "project": "standards", + "type": "standards", + "modules_count": 11, + "source": "hand-authored" +} \ No newline at end of file diff --git a/standards/mcp/standards/modules/composition_root.json b/standards/mcp/standards/modules/composition_root.json new file mode 100644 index 0000000..0011498 --- /dev/null +++ b/standards/mcp/standards/modules/composition_root.json @@ -0,0 +1,8 @@ +{ + "module": "composition_root", + "content": { + "path": "composition_root", + "docstring": "# Composition Root\n\n## Summary\n\nAll wiring happens in exactly one module. It builds a **flat resource\nregistry** and exposes it to the HTTP layer and to scripts.\n\n---\n\n## The resource registry\n\n`init.py` returns a plain `dict[str, Any]`. Keys follow two conventions:\n\n- `_repo` — a repository adapter for a resource.\n- `_svc` — a service for a resource.\n\nPlus named infrastructure adaptors:\n\n- `http_cache_store` — response cache backend.\n- `progress_bus` — progress/event bus.\n- `_` — fetchers, clients, stores.\n\nThe API stores the dict on `app.state.resources` during lifespan startup.\nHandlers read from it; nothing imports concrete adapters.\n\n## Shape\n\n```python\n_resources: dict = {}\n_initialized = False\n\nasync def init(settings=None) -> dict:\n global _initialized\n if _initialized:\n return _resources\n\n await setup_database(uri=settings.mongo_uri, db_name=settings.mongo_db)\n\n # 1. leaf repositories\n user_repo = create_user_repo()\n\n # 2. dependent repositories (dependencies passed by keyword)\n wallet_repo = create_wallet_repo(user_repo=user_repo)\n\n # 3. services (build via the DI library, injecting the repo)\n _resources[\"user_repo\"] = user_repo\n _resources[\"wallet_repo\"] = wallet_repo\n _resources[\"user_svc\"] = get_user_service(user_repo)\n _resources[\"wallet_svc\"] = get_wallet_service(wallet_repo)\n\n # 4. infrastructure adaptors (optional)\n _resources[\"http_cache_store\"] = HttpCacheStore(...)\n _resources[\"progress_bus\"] = ProgressEventBus()\n\n _initialized = True\n return _resources\n\nasync def shutdown() -> None:\n global _initialized\n await close_stores(_resources)\n await shutdown_database()\n _resources.clear()\n _initialized = False\n```\n\n## Typed accessors\n\nExpose a `get_svc(name)` helper with one `@overload` per key so scripts get\ntyping without importing concrete classes:\n\n```python\n@overload\ndef get_svc(name: Literal[\"user_svc\"]) -> UserService: ...\n@overload\ndef get_svc(name: Literal[\"wallet_svc\"]) -> WalletService: ...\n\ndef get_svc(name: str):\n return _resources[name]\n```\n\nAlso expose `get_db()` (raw database handle) and pure helpers such as\n`compute_fingerprint(payload)` (canonical hash used for deduplication).\n\n## Rules\n\n- `init()` is **idempotent**.\n- The composition root is the only place that imports concrete adapters.\n- Handlers never call `init()`; they read `request.app.state.resources`.\n- Scripts call `init()` / `shutdown()` around their work.\n", + "objects": {} + } +} \ No newline at end of file diff --git a/standards/mcp/standards/modules/crud_template.json b/standards/mcp/standards/modules/crud_template.json new file mode 100644 index 0000000..f2d855a --- /dev/null +++ b/standards/mcp/standards/modules/crud_template.json @@ -0,0 +1,8 @@ +{ + "module": "crud_template", + "content": { + "path": "crud_template", + "docstring": "# CRUD Template\n\n## Summary\n\nEvery resource follows the same four-file slice. Repetition is intentional: it\nmakes the codebase predictable and generatable.\n\n---\n\n## The slice\n\n```\ndomain//\n models.py # pure Pydantic model (no DB fields)\n ports/\n db.py # document model + repository factory\n service.py # service class + factory\n converters.py # (optional) transforms\n```\n\n## models.py\n\nA framework-free Pydantic model describing the business shape.\n\n```python\nclass Item(BaseModel):\n name: str\n quantity: int = 0\n```\n\n## ports/db.py\n\nThe persistence model extends the business model and adds database concerns.\nThe repository factory selects the right repository flavour.\n\n```python\nclass ItemDocument(Item, BaseDocument): # BaseDocument adds id/created_at/...\n pass\n\ndef create_item_repo(*, owner_repo=None) -> ItemRepository:\n return repo_factory(\n collection=\"items\",\n document=ItemDocument,\n populate_rules=[PopulateRule(field=\"owner\", collection=\"users\")],\n cache=None, # or a CachedBaseRepository config\n )\n```\n\n## ports/service.py\n\nThe service is built through the DI library, injecting the repository. The\ngeneric CRUD base provides `create/read/update/patch/delete/search/...`.\n\n```python\nclass ItemService(CrudsServiceAdaptor[Item, ItemDocument]):\n model = Item\n schema = ItemDocument\n\ndef get_item_service(repo) -> ItemService:\n return build(ItemService, instances={\"repo\": repo})\n```\n\n## Naming conventions\n\n| Concept | Convention |\n|---|---|\n| collection | plural snake case (`items`) |\n| document | `Document` |\n| repository factory | `create__repo` |\n| service | `Service` |\n| service factory | `get__service` |\n| resource key | `_svc` |\n| operationId | `list_items`, `create_item`, ... |\n\n## Optional files\n\n- `converters.py` — pure functions mapping between domain types.\n- `ports/enrichment.py` — adapts a pipeline into an async callable the service\n can invoke (used when a resource is populated by a pipeline).\n", + "objects": {} + } +} \ No newline at end of file diff --git a/standards/mcp/standards/modules/genericity_matrix.json b/standards/mcp/standards/modules/genericity_matrix.json new file mode 100644 index 0000000..18253f3 --- /dev/null +++ b/standards/mcp/standards/modules/genericity_matrix.json @@ -0,0 +1,8 @@ +{ + "module": "genericity_matrix", + "content": { + "path": "genericity_matrix", + "docstring": "# Genericity Matrix\n\n## Summary\n\nThis page states precisely what is **reusable as-is**, what is a **template to\nadapt**, and what is **app-specific and must be authored**. Use it to scope a\nnew build.\n\n---\n\n## Reusable as-is (do not rewrite)\n\n| Area | Artifact |\n|---|---|\n| Layering & dependency rule | the package layout and import rules |\n| Composition root | the `init.py` shape, idempotency, `get_svc` overloading |\n| Web edge | `OpenAPIFirstApp` bootstrap, handler-name = `operationId`, thin handlers |\n| CRUD slice | the four-file pattern (model / ports-db / ports-service / converters) |\n| Generic CRUD service | the base service adaptor |\n| Repository factory | base / populating / cached selection |\n| Worker | the poll loop, backoff, retry, status machine |\n| Progress bus | the bus port + in-memory adapter + streaming endpoint |\n| Human-in-the-loop | the durable pause + question document + resolve endpoint + resume map |\n| Infra adaptors | HTTP cache decorator, KV store port, LLM pool scaffold |\n| Testing | integration harness with fakes, fixture-parity pattern |\n| Docs | GSDFC + generated stubs + MCP bundle pipeline |\n\n## Template to adapt (copy, then change names)\n\n| Artifact | Change |\n|---|---|\n| `pyproject.toml` | project name, dependencies |\n| `Dockerfile` / `docker-compose.yaml` | service name, ports, services |\n| `.env.example` | connection strings, provider keys |\n| `openapi.yaml` | every path/schema/operationId |\n| `scripts/` | seed and operator tasks |\n\n## App-specific (must be authored)\n\n| Artifact | Why |\n|---|---|\n| Resource models | the business shape |\n| Repository populate/cache rules | the relationships |\n| Service business logic | domain behaviour |\n| Pipeline families (if any) | the transformation graph |\n| Pattern/rule resources | data-driven policy |\n| Fixtures & golden outputs | test data |\n\n## The two axes\n\nEverything app-specific reduces to **two axes**:\n\n1. **Resource model** — the set of resources, their fields, relationships, and\n the OpenAPI contract.\n2. **Pipeline family** — only if inputs require multi-step transformation.\n\nIf you can specify those two axes, the rest of the app follows mechanically.\n", + "objects": {} + } +} \ No newline at end of file diff --git a/standards/mcp/standards/modules/human_in_loop.json b/standards/mcp/standards/modules/human_in_loop.json new file mode 100644 index 0000000..ea11e76 --- /dev/null +++ b/standards/mcp/standards/modules/human_in_loop.json @@ -0,0 +1,8 @@ +{ + "module": "human_in_loop", + "content": { + "path": "human_in_loop", + "docstring": "# Human-in-the-Loop\n\n## Summary\n\nSome inputs are ambiguous and must be resolved by a human before processing can\ncontinue. The blueprint models this as a **durable pause**: an exception is\nraised, a question is recorded, the job pauses, and later resumes.\n\n---\n\n## The mechanism\n\n1. During processing, a stage raises a domain exception carrying the context\n needed to ask the question:\n\n ```python\n raise PauseForResolution(\n job_id=jid,\n reference=\"\",\n options=[...],\n context={...},\n )\n ```\n\n2. The orchestrator catches it, records a **question document**, and re-raises\n so the worker marks the job `paused`.\n3. A client lists pending questions and answers one:\n\n ```\n GET /jobs/{id}/questions -> list pending questions\n POST /questions/{qid}/resolve {choice} -> record the choice\n ```\n\n4. When the **last** pending question is resolved, the resolve endpoint flips\n the parent job back to `pending`.\n5. The worker picks it up again, rebuilds a **resolution map** from previously\n answered questions, and seeds it into the pipeline so the same decision is\n not asked twice.\n\n## The question document\n\n```python\nclass Question(BaseDocument):\n job_id: str\n reference: str # stable key: stage|field|value\n status: str # pending | resolved\n options: list[dict]\n context: dict\n chosen: dict | None = None\n resolved_at: str | None = None\n```\n\n## Resume map\n\nThe worker turns answered questions into a lookup keyed by `reference`, then\ninjects it into the pipeline so that stage can skip re-raising:\n\n```python\nresolved = {q.reference: q.chosen for q in await svc.search(\n filter={\"job_id\": jid, \"status\": \"resolved\"})}\n\npipeline = build(root, instances={\"pause\": handler}, config={\"resolved\": resolved})\n```\n\n## Resolve endpoint\n\n```python\nasync def resolve_question(request, id, body):\n svc = request.app.state.resources[\"question_svc\"]\n q = await svc.read(id)\n await svc.update(id, {\"chosen\": body[\"chosen\"], \"status\": \"resolved\",\n \"resolved_at\": now()})\n\n pending = await svc.search(filter={\"job_id\": q.job_id, \"status\": \"pending\"},\n limit=1)\n if not pending:\n jobs = request.app.state.resources[\"job_svc\"]\n job = await jobs.read(q.job_id)\n if job and job.status == \"paused\":\n await jobs.update_status(q.job_id, \"pending\")\n return q\n```\n\n## CLI parity\n\nThe same flow is available through scripts/CLI: `list`, `get`, `create`,\n`questions`, `resolve`, `retry`.\n", + "objects": {} + } +} \ No newline at end of file diff --git a/standards/mcp/standards/modules/index.json b/standards/mcp/standards/modules/index.json new file mode 100644 index 0000000..6ea50b1 --- /dev/null +++ b/standards/mcp/standards/modules/index.json @@ -0,0 +1,8 @@ +{ + "module": "index", + "content": { + "path": "index", + "docstring": "# Standards Reference\n\nThe reference half of the Standards description: the enforceable rules,\npatterns, and the internal library catalog that agents consult while coding.\n\n- **Layering Rules** — the strict request → domain → repository layering and\n the rules that enforce it.\n- **Composition Root** — a single composition point wiring the whole app.\n- **Spec-First Routing** — the OpenAPI contract as the routing source of truth.\n- **CRUD Template** — the standardized generic resource endpoint scaffold.\n- **Pipeline Scaffold** — the deterministic pipeline skeleton for multi-stage\n jobs.\n- **Worker & Progress** — queued work, progress reporting, and visibility.\n- **Human-in-the-Loop** — guardrails and approvals inside automations.\n- **Infra Adapters** — how infrastructure connects without leaking into domain.\n- **Genericity Matrix** — what is generic vs app-specific.\n- **Library Registry** — the catalog of internal libraries behind all of it.\n\nRead the **Wiki** for the philosophy and rationale; these pages are the\nreference that mirrors the `standards` MCP bundle.\n", + "objects": {} + } +} \ No newline at end of file diff --git a/standards/mcp/standards/modules/infra_adaptors.json b/standards/mcp/standards/modules/infra_adaptors.json new file mode 100644 index 0000000..bb00edb --- /dev/null +++ b/standards/mcp/standards/modules/infra_adaptors.json @@ -0,0 +1,8 @@ +{ + "module": "infra_adaptors", + "content": { + "path": "infra_adaptors", + "docstring": "# Infra Adapters\n\n## Summary\n\nAll external systems are reached through adapters in `infra/`. Prefer an\nexisting internal library over writing a new adapter.\n\n---\n\n## Database (MongoDB)\n\n- A single connection manager owns the client lifecycle.\n `setup_database(uri, db_name)` / `shutdown_database()`.\n- A repository **factory** selects the repository flavour:\n\n ```python\n repo_factory(collection, document, engine=None,\n populate_rules=None, cache=None)\n ```\n\n - base repository — plain CRUD;\n - populating repository — resolves referenced documents (foreign keys);\n - cached repository — an LRU/TTL cache in front of reads.\n\n- Referenced documents are described declaratively:\n\n ```python\n PopulateRule(field=\"owner\", collection=\"users\",\n nested_rules=[], max_depth=2, projection=None)\n ```\n\n- Transactions use a session context manager provided by the library.\n\n**Library:** the Mongo operations library (see registry). Do not write raw\nMotor calls in the domain.\n\n## HTTP response cache\n\nA generic GET cache sits behind a decorator.\n\n```python\n@cache_response(ttl=60)\nasync def list_items(request): ...\n```\n\n- Keyed on path + query + user.\n- No-op when no store is wired.\n- `invalidate(*resources)` bumps a generation counter for write-triggered\n invalidation.\n\n## Event / progress bus\n\nA port with an in-memory default adapter (`publish`, `get_events`). Swap for a\ndurable broker in production (see Worker & Progress).\n\n## External clients (ingestion)\n\nExternal fetchers (files, mail, HTTP) are adapters that wrap ingestion\nlibraries. Construct them in the composition root and inject into\norchestrators.\n\n**Libraries:** the ingestion library (formats) and the mail library (email).\n\n## LLM clients\n\nWhen a pipeline calls a model provider, route through a pool adaptor that\nhandles provider selection, retries, and client lifecycle:\n\n```python\npool = setup_async_pool(provider=settings.llm_provider)\nresult = await pool.complete(model=\"...\", messages=[...])\n```\n\nProviders are selected by `LLM_PROVIDER` and configured by environment.\n\n## Key-value store\n\nFor report/snapshot storage, provide a pluggable store port with a Redis\nadapter and an in-memory fallback.\n\n## Rule\n\nIf a capability already exists as a library (DB, DI, ingestion, mail, auth,\ndocs), **use it**. Writing a private copy of a library is a defect.\n", + "objects": {} + } +} \ No newline at end of file diff --git a/standards/mcp/standards/modules/layering_rules.json b/standards/mcp/standards/modules/layering_rules.json new file mode 100644 index 0000000..594b7e1 --- /dev/null +++ b/standards/mcp/standards/modules/layering_rules.json @@ -0,0 +1,8 @@ +{ + "module": "layering_rules", + "content": { + "path": "layering_rules", + "docstring": "# Layering Rules\n\n## Summary\n\nThe dependency direction is fixed. Violating it is a design defect.\n\n---\n\n## Allowed imports\n\n```\ninterfaces/* -> domain/* (services, ports, models)\ninterfaces/* -> infra/adapters/* (only read-only value objects)\ndomain/* -> domain/* (same layer)\ndomain/* -> pipelines/* (call a pipeline via a port)\ninfra/adapters/* -> domain/ports/* (implement the interface)\nmain.py/init.py -> everything (composition root only)\n```\n\n## Forbidden imports\n\n```\ndomain/* -> interfaces/* (never)\ndomain/* -> fastapi/starlette (never)\ninfra/adapters/* -> interfaces/* (never)\ninterfaces/* -> infra/db/* (state lives in resources, not imports)\n```\n\n## Why\n\n- A pure domain is testable without a server, a database, or an event loop.\n- Adapters can be swapped (in-memory fake, real database) without touching\n business logic.\n- The HTTP edge stays thin and replaceable.\n\n## The port/adapter contract\n\nA **port** is an abstract class or protocol declared in `domain//ports/`.\nAn **adapter** implements it in `infra/adapters/`. The composition root binds\nthe two.\n\n```\ndomain//ports/db.py -> repository port + document model\ndomain//ports/service.py -> service + factory\ninfra/db/repos/.py -> repository adapter factory\ninfra/adapters/service.py -> generic CRUD service base\n```\n\n## Enforcement\n\n- Keep every domain module importable with only the standard library and\n Pydantic. If a domain import pulls in `fastapi`, the layering is broken.\n- Reviewers (and CI) reject `import fastapi` inside `domain/` or `infra/`.\n", + "objects": {} + } +} \ No newline at end of file diff --git a/standards/mcp/standards/modules/library_registry.json b/standards/mcp/standards/modules/library_registry.json new file mode 100644 index 0000000..b8096de --- /dev/null +++ b/standards/mcp/standards/modules/library_registry.json @@ -0,0 +1,8 @@ +{ + "module": "library_registry", + "content": { + "path": "library_registry", + "docstring": "# Library Registry\n\n## Summary\n\nThe Aetos ecosystem provides internal libraries for the shared concerns of\nevery application. **Use them.** Writing a private copy of any capability below\nis a defect.\n\nEach library also exposes its own documentation as an MCP server. An AI agent\ncan read a library's full API by connecting to its MCP and reading\n`docs://index`, `docs://nav`, and `docs://modules/{module}`.\n\n---\n\n## Catalog\n\n| Library | Import | Purpose | Use instead of | MCP |\n|---|---|---|---|---|\n| DAG Pipe | `dagpipe` | Deterministic state-transformation DAG engine | hand-rolled orchestration/topological ordering | `:8006` |\n| Hexa | `hexa` | Declarative DI / composition-root tooling | manual wiring, hand-written factories | *(see note)* |\n| Mongo Ops | `mongo_ops` | Async MongoDB repositories, cache, populate, transactions | raw Motor CRUD and connection lifecycle | `:8007` |\n| Omniread | `omniread` | Format-agnostic fetch + parse (HTML, PDF, CSV, XLSX) | custom scrapers/parsers | `:8003` |\n| OpenAPI First | `openapi_first` | Spec-first FastAPI bootstrap, client, codegen | decorator routers and hand-written clients | `:8004` |\n| Mail Intake | `mail_intake` | Provider-agnostic read-only email ingestion | Gmail OAuth + MIME parsing | `:8002` |\n| Py JWT | `jwtlib` | JWT auth primitives (register/login/introspect) | password hashing + token code | `:8005` |\n| Doc Forge | `docforge` | Docstring compiler → MkDocs + MCP docs | custom doc generators | `:8001` |\n| Auth Server | *(service)* | Central identity service (register/login/me/introspect) | building auth endpoints yourself | — |\n\n## How to choose\n\n| You need to… | Use |\n|---|---|\n| persist and query documents | Mongo Ops |\n| compose dependencies | Hexa |\n| run a multi-step transformation | DAG Pipe |\n| read/parse an arbitrary input format | Omniread |\n| expose a contract-first HTTP API | OpenAPI First |\n| ingest email | Mail Intake |\n| authenticate users / verify tokens | Py JWT (+ Auth Server) |\n| generate documentation | Doc Forge |\n\n## Discovery\n\nA single **standards MCP** exposes `find_library(capability)`, which returns the\nmatching library, its import name, its \"use instead of\" guidance, and its MCP\nendpoint. Query it before writing any infrastructure.\n\n## Notes\n\n- **Hexa** ships an MCP bundle but is not yet assigned a dedicated port in the\n hub config; it is reachable via the standards registry entry and will be\n wired to a port.\n- Library MCP servers expose **documentation resources** (not executable tools):\n they tell an agent the available API surface so it does not invent code.\n", + "objects": {} + } +} \ No newline at end of file diff --git a/standards/mcp/standards/modules/pipeline_scaffold.json b/standards/mcp/standards/modules/pipeline_scaffold.json new file mode 100644 index 0000000..c15078e --- /dev/null +++ b/standards/mcp/standards/modules/pipeline_scaffold.json @@ -0,0 +1,8 @@ +{ + "module": "pipeline_scaffold", + "content": { + "path": "pipeline_scaffold", + "docstring": "# Pipeline Scaffold\n\n## Summary\n\nData-driven processing is expressed as a **composition graph**. The graph is\nbuilt by a DI library; execution is driven by a DAG engine. Stages are pure and\nindividually testable.\n\n---\n\n## When to use a pipeline\n\nUse a pipeline when a resource is produced by a **multi-step transformation**\nof an input (a document, a file, a message) rather than by a simple CRUD write.\n\n## Structure of a family\n\nA **family** is one input shape (e.g. a file format or a message kind). Each\nfamily has the same skeleton:\n\n```\npipelines//\n abc.py # port contracts (stage interfaces + root interface)\n impl.py # concrete stages + root implementation\n pipeline.yaml # graph spec: nodes, edges, roots, schema\n resources/\n pipeline.yaml # runtime spec consumed by the loader\n patterns/*.yaml # rule fragments (pattern registry)\n banks/.py # optional variants that re-pin a few slots\n```\n\n## Shared scaffolding\n\n```\npipelines/shared/\n ports.py # RegistryPort, FinalizePort, etc.\n loader.py # build(root_cls) -> wires the graph + engine\n registry.py # resolve_root(...) -> root class for a (kind, variant)\n```\n\n## The loader\n\n```python\ndef build(root_cls, *, instances=None, config=None):\n # merge resources/patterns/*.yaml into a pattern registry\n # bind registry/config into each graph node by id\n # build the schema (state) class and the engine\n root = root_cls()\n root._engine = Engine(graph, state_cls, payload_cls)\n return root\n```\n\n## The registry\n\nA single lookup replaces hand-rolled `if/else` selection:\n\n```python\n_FAMILIES = {\n \"csv\": {\"acme\": {\"heuristic\": AcmeCsvPipeline}},\n \"json\": {\"globex\": {\"heuristic\": GlobexJsonPipeline}},\n}\n\ndef resolve_root(kind, variant, mode=\"heuristic\"):\n return _FAMILIES[kind][variant][mode]\n```\n\nAdding a new variant means adding one class and one registry entry.\n\n## Driving a pipeline\n\nStages are driven explicitly so intermediate state can be persisted:\n\n```python\npipeline = build(resolve_root(kind, variant))\ncontent = pipeline.ingest.materialize(raw_bytes)\nrecords = pipeline.reader.read(content)\nitems = pipeline.normalize.build(records)\n```\n\n## Testing\n\nBecause stages are pure, test each stage in isolation and test the assembled\nroot against **fixture inputs** whose expected outputs are stored as golden\nfiles. A parity test replays fixtures headlessly.\n", + "objects": {} + } +} \ No newline at end of file diff --git a/standards/mcp/standards/modules/spec_first_routing.json b/standards/mcp/standards/modules/spec_first_routing.json new file mode 100644 index 0000000..9db3023 --- /dev/null +++ b/standards/mcp/standards/modules/spec_first_routing.json @@ -0,0 +1,8 @@ +{ + "module": "spec_first_routing", + "content": { + "path": "spec_first_routing", + "docstring": "# Spec-First Routing\n\n## Summary\n\nThe OpenAPI document is the single source of truth for the HTTP contract.\nHandlers are bound to it by name; there is no decorator router.\n\n---\n\n## The contract\n\n- `openapi.yaml` (or `.json`) declares paths, schemas, parameters, responses,\n and security.\n- A custom `operationId` names the handler function.\n- The framework (`openapi_first`) validates requests/responses against the\n spec and dispatches to the handler whose name equals `operationId`.\n\n## App bootstrap\n\n```python\n# main.py\nfrom openapi_first.app import OpenAPIFirstApp\n\napp = OpenAPIFirstApp(\n openapi_path=\"openapi.yaml\",\n routes_module=interfaces.openapi, # module whose namespace holds handlers\n title=\" API\",\n version=\"0.1.0\",\n lifespan=lifespan,\n)\n```\n\n`lifespan` calls the composition root:\n\n```python\n@asynccontextmanager\nasync def lifespan(app):\n app.state.resources = await init()\n yield\n await shutdown()\n```\n\n## Handler registry\n\n`interfaces/openapi.py` is a flat re-export of every handler, so the framework\ncan resolve `operationId` across the whole app:\n\n```python\nfrom interfaces.item.routes import *\nfrom interfaces.wallet.routes import *\nfrom interfaces.progress.sse import *\n```\n\n## Handler shape\n\nHandlers are thin and synchronous with respect to business logic:\n\n```python\nasync def create_item(request: Request, body: dict):\n svc = request.app.state.resources[\"item_svc\"]\n return await svc.create(Item.model_validate(body))\n```\n\n## Conventions\n\n- `operationId` naming: `list_`, `create_`,\n `get_`, `update_`, `delete_`.\n- Read-only endpoints may use a cache decorator keyed on path + query + user.\n- Validation errors -> `400`; not found -> `404`; delete -> `204`.\n- Security is declared once in the spec and enforced by the framework; handlers\n contain no auth code.\n\n## Codegen\n\nThe `openapi_first` library can scaffold models and route stubs from the spec,\nand ships app templates (CRUD app, model app, service). Prefer codegen over\nhand-writing boilerplate.\n", + "objects": {} + } +} \ No newline at end of file diff --git a/standards/mcp/standards/modules/worker_and_progress.json b/standards/mcp/standards/modules/worker_and_progress.json new file mode 100644 index 0000000..09d79ef --- /dev/null +++ b/standards/mcp/standards/modules/worker_and_progress.json @@ -0,0 +1,8 @@ +{ + "module": "worker_and_progress", + "content": { + "path": "worker_and_progress", + "docstring": "# Worker & Progress\n\n## Summary\n\nLong-running work runs in a background worker. Jobs are durable documents that\nmove through an explicit status machine. Progress is streamed to clients.\n\n---\n\n## The status machine\n\n```\npending -> processing -> completed\n \\-> failed (retried up to N times)\n \\-> paused (waiting for human input)\n```\n\n- `pending` — queued, eligible for pickup.\n- `processing` — claimed by a worker.\n- `paused` — blocked on a human-in-the-loop question.\n- `failed` — error; `retry_count` increments until a max, then skipped.\n- `completed` — terminal success.\n\n## The poll loop\n\n```python\nasync def poll(resources):\n backoff = MIN_POLL\n while True:\n jobs = await job_svc.search(filter={\"status\": \"pending\"}, limit=100)\n backoff = MIN_POLL if jobs else min(backoff * 2, MAX_POLL)\n for job in jobs:\n if (job.retry_count or 0) >= MAX_RETRIES:\n continue\n await job_svc.update_status(job.id, \"processing\")\n try:\n await process(job, resources)\n except PauseForResolution:\n await job_svc.update_status(job.id, \"paused\")\n except Exception as e:\n await job_svc.update_status(\n job.id, \"failed\", error=str(e),\n retry_count=(job.retry_count or 0) + 1,\n )\n await asyncio.sleep(backoff)\n```\n\nTunables live in environment variables: `WORKER_POLL_MIN`, `WORKER_POLL_MAX`,\n`WORKER_MAX_RETRIES`.\n\n## Progress events\n\nA worker publishes structured progress events to a **bus** (a port). The HTTP\nedge exposes a streaming endpoint that replays events for a given job id.\n\n```python\nclass ProgressEvent(BaseModel):\n job_id: str\n step: str\n status: str # started | progress | completed | skipped | paused\n message: dict | None = None\n```\n\nThe bus is an in-memory adapter by default; because it is a port, it can be\nswapped for a durable broker. Emit from the orchestrator at each stage:\n\n```python\nawait self.bus.publish(ProgressEvent(job_id=jid, step=\"normalize\",\n status=\"completed\", message={\"count\": n}))\n```\n\n## Streaming endpoint\n\n```python\nasync def stream_job_events(request, id):\n bus = request.app.state.resources.get(\"progress_bus\")\n if bus is None:\n return {\"events\": []}\n\n async def gen():\n sent = 0\n while True:\n events = bus.get_events(id)\n for e in events[sent:]:\n yield f\"data: {e.model_dump_json(exclude_none=True)}\\n\\n\"\n sent += 1\n await asyncio.sleep(0.5)\n\n return StreamingResponse(gen(), media_type=\"text/event-stream\")\n```\n\n> **Known limitation.** The default in-memory bus is per-process. If the worker\n> and the API run as separate processes, events published by the worker are not\n> visible to the API. For production, back the bus with a shared broker. The\n> port boundary makes this a one-adapter change.\n", + "objects": {} + } +} \ No newline at end of file diff --git a/standards/mcp/standards/nav.json b/standards/mcp/standards/nav.json new file mode 100644 index 0000000..6a08db3 --- /dev/null +++ b/standards/mcp/standards/nav.json @@ -0,0 +1,57 @@ +[ + { + "module": "layering_rules", + "resource": "doc://modules/layering_rules", + "title": "Layering Rules" + }, + { + "module": "composition_root", + "resource": "doc://modules/composition_root", + "title": "Composition Root" + }, + { + "module": "spec_first_routing", + "resource": "doc://modules/spec_first_routing", + "title": "Spec-First Routing" + }, + { + "module": "crud_template", + "resource": "doc://modules/crud_template", + "title": "CRUD Template" + }, + { + "module": "pipeline_scaffold", + "resource": "doc://modules/pipeline_scaffold", + "title": "Pipeline Scaffold" + }, + { + "module": "worker_and_progress", + "resource": "doc://modules/worker_and_progress", + "title": "Worker & Progress" + }, + { + "module": "human_in_loop", + "resource": "doc://modules/human_in_loop", + "title": "Human-in-the-Loop" + }, + { + "module": "infra_adaptors", + "resource": "doc://modules/infra_adaptors", + "title": "Infra Adapters" + }, + { + "module": "genericity_matrix", + "resource": "doc://modules/genericity_matrix", + "title": "Genericity Matrix" + }, + { + "module": "library_registry", + "resource": "doc://modules/library_registry", + "title": "Library Registry" + }, + { + "module": "index", + "resource": "doc://modules/index", + "title": "Standards Reference" + } +] \ No newline at end of file