Skip to content

Feature: MCP server exposing REST API with identical authz (incl. MyOpenCRE) #1003

Closed

Description

@northdpole

Issue

What is the issue?

Add an MCP (Model Context Protocol) server for OpenCRE that exposes the same capabilities as the existing REST API (/rest/v1/..., documented in docs/api/openapi.yaml), with identical authentication and authorisation requirements.

Agents and IDEs should be able to call OpenCRE through MCP the same way clients call REST today — including authenticated surfaces such as MyOpenCRE (GET/PUT /rest/v1/user/resources), chat completion (POST /rest/v1/completion), and any other @login_required / feature-flagged routes — without a weaker or parallel auth model.

Expected Behaviour

  1. Capability parity

    • MCP tools (and resources/prompts where appropriate) map 1:1 (or via a thin, documented mapping) to OpenAPI operations under /rest/v1.
    • Public endpoints remain callable without login (same as REST).
    • Protected endpoints require the same login / feature gates as REST, e.g.:
      • MyOpenCRE: CRE_ENABLE_LOGIN + CRE_ENABLE_MYOPENCRE + authenticated session (login_required) for /rest/v1/user/resources
      • Chat: login_required on /rest/v1/completion
      • Admin import routes: same login_required (and any admin checks) as today
    • Unauthenticated or unauthorized MCP calls fail with the same effective outcomes as REST (401 / feature-disabled defaults), not silent empty success unless REST already does that (see feature_enabled_or_default behaviour on MyOpenCRE).
  2. Authn/authz

    • Reuse the existing OAuth/session model (or an explicitly designed, equivalent token flow that maps to the same session/user identity).
    • No separate “MCP bypass” or shared static secret that grants MyOpenCRE / chat / admin powers.
    • Document how a Cursor/Claude/other MCP client obtains and supplies credentials for local and for hosted (opencre.org) use.
  3. Delivery

    • Runnable locally and (if in scope) against production/staging OpenCRE.
    • Documented install/config for at least one common MCP client (e.g. Cursor).
    • Tests covering: public tool, auth-required tool denied without credentials, auth-required tool succeeds with credentials, MyOpenCRE feature-flag off behaviour matches REST.

Actual Behaviour

There is no OpenCRE MCP server; agents must invent ad-hoc HTTP calls and cannot reliably share REST authz semantics (especially for MyOpenCRE and other login-gated routes).

Steps to reproduce

N/A (feature request).


Success criteria

  • MCP server implements tools covering OpenAPI /rest/v1 operations (or an agreed phased subset with a tracked gap list ending in full parity).
  • Authn/authz for each tool matches the corresponding REST route (login_required, feature flags, admin rules).
  • MyOpenCRE user/resources GET/PUT work over MCP only when REST would allow them.
  • Docs: client setup, auth flow, tool ↔ REST mapping table.
  • Automated tests for public vs authenticated vs feature-gated paths.
  • make lint / make mypy / make test (and any new MCP-specific checks) green.

Context

Design questions (to resolve in planning)

  1. Transport: local stdio MCP proxy to REST vs remote HTTP MCP hosted with the app?
  2. Auth UX: browser OAuth + cookie/session forwarding vs device-code / PAT / API token bound to the same user record?
  3. Phasing: ship public read tools first, then MyOpenCRE + completion, then admin — or full parity in one release?
  4. Implementation home: in-repo Python package vs separate npm/Python MCP package that calls REST?

Constraints

  • Must not weaken REST security for MCP convenience.
  • Prefer reusing OpenAPI as the source of truth for tool schemas rather than hand-maintaining a divergent surface.
  • No production DB destructive ops; MCP must not expose privileged internal scripts beyond what REST already exposes.
  • Mocks: not for authz tests — exercise real Flask auth gates (or equivalent integration) where practical.

Out of scope (unless explicitly pulled in)

Activity

  1. nolanefe commented on Aug 3, 2026

    @nolanefe
    Contributor

    Hi, I’d like to work on this issue if it is still available.

    I’ll first trace the existing REST/OpenAPI surface in docs/api/openapi.yaml, the Flask route registration in application/web/web_main.py, and the current auth helpers (login_required, feature gates, and MyOpenCRE checks). Then I’d like to build the MCP layer as a thin adapter over the existing REST contracts rather than creating a separate authorization model.

    My proposed implementation would:

    • use the existing OpenAPI/REST definitions as the source of truth for MCP tool schemas and avoid maintaining a divergent hand-written API surface
    • map MCP tools to the corresponding /rest/v1 operations with explicit documentation of each tool-to-REST relationship
    • preserve the same public, authenticated, feature-gated, and admin authorization behavior as the corresponding REST routes
    • avoid introducing any shared MCP bypass secret or broader permissions than REST already provides
    • make authentication failures and disabled-feature behavior match the effective REST outcomes rather than silently returning successful empty results
    • cover MyOpenCRE user/resources access so GET/PUT operations succeed over MCP only when the equivalent REST request would be authorized
    • add integration tests for public access, unauthenticated denial, authenticated success, feature-flag-disabled behavior, and authorization boundaries
    • add MCP client setup documentation and an auth-flow example for at least one common client such as Cursor
    • keep destructive/internal functionality out of the MCP surface unless it is already exposed through the supported REST API
    • run the existing make lint, make mypy, and make test checks together with any MCP-specific tests

    Since the issue leaves transport, authentication UX, and rollout phasing open, which direction would you prefer for the first PR: a smaller local stdio MCP implementation exposing the public REST-backed tools first, or should the initial contribution include authenticated/MyOpenCRE tools and the full auth flow as well?

  2. bhanu-prakash920 commented on Aug 7, 2026

    @bhanu-prakash920

    Hi @northdpole! I'd love to work on this issue. Could you please assign it to me if it's still available? Thank you!

  3. shiwani42 commented on Aug 9, 2026

    @shiwani42
    Contributor

    Hi @northdpole, I’d like to take this if it’s still available.

    I’ve traced the REST/OpenAPI surface (docs/api/openapi.yaml, web_main.py) and the auth helpers (login_required, feature_enabled_or_default, MyOpenCRE flags). My intent is a thin MCP adapter over the existing REST contracts, not a parallel auth model.

    Proposed direction for the first PR

    • Local stdio MCP that calls a running OpenCRE via OPENCRE_BASE_URL (local Flask or hosted).
    • MCP tools mapped from OpenAPI for the public /rest/v1 reads first (skip user/resources until auth lands).
    • In-repo under something like application/mcp/.
    • No MCP bypass secret; authz stays in Flask.
    • Docs for Cursor setup + a tool ↔ REST table.
    • Tests that public tools match the corresponding REST responses; make lint / make mypy / make test green.

    Follow-up PR (after ack)

    • Forward the browser session cookie after normal Google login for protected calls.
    • MyOpenCRE GET/PUT /rest/v1/user/resources with the same outcomes as REST (including feature-flag-off empty 200).
    • Authz tests: denied without credentials, success with credentials, flag-off matches REST.

    I’d defer admin/CSV import tools until #966 lands, and treat hosted HTTP MCP as a later phase.

    Questions before I start coding

    1. For the first PR, are you okay with me shipping only the public read tools over local stdio that call REST, and saving the authenticated ones for the next PR?
    2. For login-gated tools I’m planning to reuse the existing Google login session (pass the session cookie), since that keeps authz inside Flask and avoids a new token model. Do you want a separate PAT/device-code instead?
    3. Chat (POST /rest/v1/completion) needs login and is not in the OpenAPI file. Should the first auth PR include a chat MCP tool anyway, or leave chat for a later PR?

    Please assign me if this plan works.

  4. northdpole commented on Aug 12, 2026

    @northdpole
    CollaboratorAuthor

    Assigning to @nolanefe as the first volunteer — thanks for the clear plan.

    @bhanu-prakash920 @shiwani42 thanks for offering as well! If this one is taken, please check other good first issue / help wanted tickets, or coordinate with @nolanefe if you want to collaborate on a follow-up PR (e.g. more tools / remote transport).

  5. northdpole commented on Aug 12, 2026

    @northdpole
    CollaboratorAuthor

    Quick direction for the first PR: no auth for MCP to start.

    Ship a local stdio MCP that only exposes public REST-backed tools (reads that work without login today). Skip MyOpenCRE, chat/completion, admin, and any cookie/PAT/session forwarding for now.

    Auth-gated tools can land in a follow-up once the public surface is solid. Prefer OpenAPI as the source of truth for tool schemas, no MCP bypass secrets (there should be nothing privileged to bypass in v1), docs for Cursor setup + tool↔REST mapping, and tests that public tools match the corresponding REST responses.

    @nolanefe — that answers your phasing question: public/local stdio first, authenticated/MyOpenCRE later.

  6. shiwani42 commented on Aug 13, 2026

    @shiwani42
    Contributor

    Thanks @northdpole for the clear direction.

    @nolanefe if you want a hand on a follow-up after the public stdio PR (auth/MyOpenCRE, chat, or remote transport later), happy to split that with you. Just ping me here.

  7. Pa04rth commented on Sep 13, 2026

    @Pa04rth
    Collaborator

    @nolanefe Whats the update ??

  8. nolanefe commented on Sep 15, 2026

    @nolanefe
    Contributor

    Thanks for checking in! The first phase of #1003 is complete: PR #1013 was merged, adding the local stdio MCP server for public OpenCRE REST reads. The broader #1003 scope remains open, with authenticated MyOpenCRE functionality, chat, and other protected surfaces still planned as follow-up work. I’m happy to continue with the next phase based on the maintainer’s direction.

  9. northdpole commented on Sep 16, 2026

    @northdpole
    CollaboratorAuthor

    Closing as completed for v1.

    Public stdio MCP (no auth, fixed public GET allowlist) shipped in #1013 (python -m application.mcp, docs/api/mcp.md). Thanks @nolanefe.

    Remaining work from this ticket (MyOpenCRE, chat, identical REST authz) is tracked in #1108.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

help wantedExtra attention is needed

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions