Skip to content

Auto-infer deployment config from mcp-app.yaml #10

@krisrowe

Description

@krisrowe

Problem

Every mcp-app solution deployed via gapp repeats identical boilerplate in gapp.yaml:

public: true
env:
  - name: SIGNING_KEY
    secret:
      generate: true
  - name: APP_USERS_PATH
    value: "{{SOLUTION_DATA_PATH}}/users"

gapp already detects mcp-app.yaml and infers the run command (mcp-app serve). But it doesn't infer env vars or public access, even though these are always identical for every mcp-app deployment.

Why these values are always the same

  • public: true — MCP clients (Claude.ai, Claude Code, Gemini CLI) authenticate with bearer tokens, not Google Cloud IAM tokens. Cloud Run IAM auth blocks all MCP clients. The auth boundary is the application (mcp-app middleware), not the infrastructure. public: true is the only practical option.
  • SIGNING_KEY — mcp-app's JWT verification needs it. Always secret: { generate: true }.
  • APP_USERS_PATH — mcp-app's FileSystemUserDataStore needs it. Always {{SOLUTION_DATA_PATH}}/users.

Proposed solution (quick)

gapp already reads mcp-app.yaml to detect the entrypoint. Read the middleware list too. If middleware is present (any middleware — they all require JWT verification), auto-inject:

  • public: true
  • SIGNING_KEY (secret, generate: true)
  • APP_USERS_PATH ({{SOLUTION_DATA_PATH}}/users)

Explicit values in gapp.yaml override auto-injected defaults.

Result: mcp-app solutions need zero gapp.yaml for standard deployments.

Architectural target (buildpack/provider pattern)

The quick fix hardcodes mcp-app knowledge in gapp. The long-term fix is a provider pattern (analogous to Heroku buildpacks / Cloud Native Buildpacks):

A provider is a bridge between a deployment platform (gapp) and a framework (mcp-app). Neither knows about the other directly. The provider reads the framework's config and translates it into deployment requirements.

  • gapp discovers providers (pip entry points, installed packages, or declared in gapp.yaml)
  • A provider declares: "I handle repos with mcp-app.yaml"
  • gapp asks the provider: how do I run you? what env vars do you need? should it be public?
  • The provider reads mcp-app.yaml and answers based on the middleware config

This keeps gapp framework-agnostic and lets new frameworks (or new mcp-app middleware types) supply their own deployment requirements without changing gapp.

Acceptance criteria

Quick fix

  • gapp reads middleware from mcp-app.yaml when detected
  • Any middleware present triggers auto-injection of SIGNING_KEY, APP_USERS_PATH, and public: true
  • Explicit values in gapp.yaml override auto-injected defaults
  • Solutions with mcp-app.yaml + middleware need zero gapp.yaml to deploy
  • Update deploy skill to document the inference behavior

Provider pattern (future)

  • Define provider interface (detect, run_command, required_env, public)
  • Implement mcp-app provider
  • gapp discovers providers via pip entry points or config
  • Document how third-party frameworks can supply providers

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions