Skip to main content
Glama
README.md
# galaxy-maps-mcp

MCP stdio server for validating, saving, publishing, and inspecting Galaxy Maps courses from local JSON files.

## Setup

Install dependencies with Bun when you are ready to run the server:

```sh
bun install
```

Runtime environment is read lazily, so the server can start without credentials. Firebase credentials are only required for tools that call Firebase.

```sh
export GALAXY_MAPS_FIREBASE_API_KEY="..."
export GALAXY_MAPS_EMAIL="..."
export GALAXY_MAPS_PASSWORD="..."
```

Optional overrides:

```sh
export GALAXY_MAPS_PROJECT_ID="galaxy-maps-ac367"
export GALAXY_MAPS_REGION="us-central1"
```

The Firebase API key value already lives in the platform repo `.env` as `VITE_FIREBASE_API_KEY`; reuse that value here as `GALAXY_MAPS_FIREBASE_API_KEY`.

## Claude MCP Registration

Add this to `~/.claude.json`:

```json
{
  "mcpServers": {
    "galaxy-maps-mcp": {
      "command": "bun",
      "args": ["/home/ian/code/galaxy-maps-mcp/src/server.ts"],
      "env": {
        "GALAXY_MAPS_FIREBASE_API_KEY": "your-api-key",
        "GALAXY_MAPS_EMAIL": "your-email",
        "GALAXY_MAPS_PASSWORD": "your-password"
      }
    }
  }
}
```

## Tools

### `validate_galaxy_map`

Input:

```json
{ "jsonPath": "/absolute/path/to/galaxy-map.json" }
```

Reads a local JSON file with `Bun.file(path).text()`. Accepts either a bare Galaxy Map object or a wrapped object:

```json
{ "galaxyMap": { "...": "..." }, "mapLayout": "zigzag" }
```

Validation checks title, description, non-empty stars, non-empty planets, and required planet mission content. The report includes star count, planet count, total payload bytes, per-planet mission field byte sizes, and warnings for large payloads. It never prints mission HTML or the full map.

### `save_galaxy_map`

Input:

```json
{ "jsonPath": "/absolute/path/to/galaxy-map.json", "mapLayout": "zigzag" }
```

`mapLayout` is optional and may be `"zigzag"` or `"spiral"`. The selected layout is explicit input first, then wrapped file `mapLayout`, then `"zigzag"`.

Flow:

1. Validate the local file.
2. Sign in with Firebase Auth REST.
3. POST to `https://{GALAXY_MAPS_REGION}-{GALAXY_MAPS_PROJECT_ID}.cloudfunctions.net/saveGalaxyMap`.
4. Return course ID, total planets, layout, and `https://app.galaxymaps.io/galaxy/{courseId}`.

### `publish_course`

Input:

```json
{
  "courseId": "course-id",
  "visibility": "unlisted",
  "presentationOnly": false
}
```

`visibility` defaults to `"unlisted"` and may be `"private"`, `"unlisted"`, or `"public"`. `presentationOnly` defaults to `false`.

Behavior:

- Public visibility patches the course to `status: "submitted"` and `visibility: "public"`, then stops because admin review is required.
- Private or unlisted visibility publishes the course.
- If the course has no cohort and `presentationOnly` is false, the tool creates a default Squad cohort and attaches it to the course.
- If `presentationOnly` is true, the course is patched with `presentationOnly: true` and `public: false`.

### `get_course_status`

Input:

```json
{ "courseId": "course-id" }
```

Reads `courses/{courseId}` from Firestore REST and returns title, status, visibility, public flag, cohort, topic total, task total, and course URL.

## Development

Run a TypeScript check:

```sh
bunx tsc --noEmit
```

Run the local handshake smoke test after dependencies are installed:

```sh
bun test/handshake.ts
```

Maintenance

ActivityInactive
ResponsivenessNo issues