Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions .github/workflows/test-node.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,41 @@ on:
- ".github/workflows/test-node.yml"
- "api/**"
workflow_dispatch:
defaults:
run:
working-directory: ./api
jobs:
test:
test-api:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./api
env:
AWS_ACCESS_KEY_ID: ci
AWS_SECRET_ACCESS_KEY: ci
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 20.x
node-version: 24.x
cache: "npm"
cache-dependency-path: 'api/package-lock.json'
cache-dependency-path: "api/package-lock.json"
- run: npm ci
- name: Check code style
run: npm run lint && npm run prettier
- name: Run tests
run: npm run test:coverage
- name: Validate OpenAPI spec
run: npm run validate-spec
test-mcp:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./mcp
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 24.x
cache: "npm"
cache-dependency-path: "mcp/package-lock.json"
- run: npm ci
- name: Run tests
run: npm run test:coverage
8 changes: 4 additions & 4 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
nodejs 20.15.0
java corretto-19.0.1.10.1
nodejs 24.11.1
java corretto-19.0.1.10.1
aws-sam-cli 1.148.0
python 3.12.2
uv 0.9.5
python 3.12.2
uv 0.9.5
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ help:
echo "make serve-https | run the SAM server locally (HTTPS on port 3002)"
echo "make style-node | run node code style check"
echo "make style-python | run python code style check"
echo "make test-mcp | run mcp tests"
echo "make test-node | run node tests"
echo "make test-python | run python tests"
echo "make cover-node | run node tests with coverage"
Expand Down Expand Up @@ -68,7 +69,14 @@ deps-api:
deps-av-download:
cd av-download/lambdas ;\
npm list >/dev/null 2>&1 || npm ci
deps-node: deps-api deps-av-download
deps-mcp:
cd mcp ;\
npm list >/dev/null 2>&1 ;\
deps=$$? ;\
test $$deps -eq 0 || npm ci
test-mcp: deps-mcp
cd mcp && npm test
deps-node: deps-api deps-av-download deps-mcp
cover-node: deps-node
cd api && npm run test:coverage
style-node: deps-node
Expand Down
5 changes: 5 additions & 0 deletions api/src/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 34 additions & 12 deletions api/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Description: dc-api-v2 API
Globals:
Function:
CodeUri: ./src
Runtime: nodejs20.x
Runtime: nodejs24.x
Architectures:
- x86_64
MemorySize: 128
Expand Down Expand Up @@ -118,9 +118,9 @@ Parameters:
Conditions:
CustomConfigSecret:
Fn::Not:
- Fn::Equals:
- !Ref ApiConfigPrefix
- ""
- Fn::Equals:
- !Ref ApiConfigPrefix
- ""
DeployAPI:
Fn::Equals: [!Ref DeployAPI, "true"]
DeployAVDownload:
Expand All @@ -129,8 +129,8 @@ Conditions:
Fn::Equals: [!Ref DeployChat, "true"]
WriteSecret:
Fn::Equals:
- !Ref WriteConfigSecret
- true
- !Ref WriteConfigSecret
- true
Resources:
#* apiDependencies:
#* Type: AWS::Serverless::LayerVersion
Expand All @@ -148,7 +148,7 @@ Resources:
Type: AWS::SecretsManager::Secret
Condition: WriteSecret
Properties:
Name:
Name:
Fn::If:
- CustomConfigSecret
- !Sub "${ApiConfigPrefix}/config/dcapi"
Expand Down Expand Up @@ -471,10 +471,10 @@ Resources:
Type: AWS::Serverless::Function
Properties:
Handler: handlers/get-provider-capabilities.handler
Description: boolean to indicate whether auth provider currently supports feature
Description: boolean to indicate whether auth provider currently supports feature
#* Layers:
#* - !Ref apiDependencies
Environment:
Environment:
Variables:
PROVIDER_CAPABILITIES: !Ref ProviderCapabilities
Policies:
Expand Down Expand Up @@ -740,6 +740,28 @@ Resources:
ApiId: !Ref dcApi
Path: /oai
Method: POST
mcpFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ../mcp
Handler: mcp/lambda.handler
Runtime: nodejs24.x
Environment:
Variables:
SECRETS_PATH: !Ref SecretsPath
Timeout: 30
MemorySize: 256
Policies:
- !Ref SecretsPolicy
Events:
ApiEvent:
Type: HttpApi
Properties:
ApiId: !Ref dcApi
Path: /mcp
Method: any
Metadata:
BuildMethod: makefile
chatWebsocketEndpoint:
Type: AWS::Serverless::Function
Condition: DeployChat
Expand All @@ -749,8 +771,8 @@ Resources:
#* Layers:
#* - !Ref apiDependencies
Environment:
Variables:
WEBSOCKET_URI: !Ref ChatWebSocketURI
Variables:
WEBSOCKET_URI: !Ref ChatWebSocketURI
Policies:
- !Ref SecretsPolicy
Events:
Expand Down Expand Up @@ -794,7 +816,7 @@ Resources:
Path: /chat/feedback
Method: POST
chatFeedbackBucket:
Type: 'AWS::S3::Bucket'
Type: "AWS::S3::Bucket"
chatFeedbackTopic:
Type: AWS::SNS::Topic
Properties:
Expand Down
2 changes: 2 additions & 0 deletions av-download/lambdas/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions mcp/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
build:
rm -rf node_modules
npm ci
npm run build

build-mcpFunction: build
cp -r dist/apps/* apps/mcp/package.json $(ARTIFACTS_DIR)
97 changes: 97 additions & 0 deletions mcp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# dc-api-mcp

A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that exposes Northwestern University Library's [Digital Collections API](https://api.dc.library.northwestern.edu/api/v2) as tools for AI assistants.

## Requirements

- Node.js 24+ (see [.tool-versions](.tool-versions))
- [mise](https://mise.jdx.dev/) (used by `bin/run.sh` to activate the correct runtime)

## Setup

```bash
npm install
```

## Configuration

The server reads the following environment variables:

| Variable | Default | Description |
| -------------- | ------------------------------------------------- | -------------------------------------------------------------------- |
| `DC_API_BASE` | `https://api.dc.library.northwestern.edu/api/v2` | Base URL for the Digital Collections API |
| `DC_IIIF_BASE` | `https://iiif.dc.library.northwestern.edu/iiif/3` | Base URL for the Digital Collections API |
| `SECRETS_PATH` | _(none)_ | The base secrets path to load configuration from AWS Secrets Manager |

## Running locally

### stdio (for Claude Desktop / Claude Code)

```bash
cd src
npm run stdio
```

Or via the wrapper script:

```bash
bin/run.sh
```

### HTTP (Streamable HTTP transport, port 3000)

```bash
cd src
npm run http
```

## Configuring Claude Desktop

Add the following entry to your Claude Desktop configuration file.

**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
"mcpServers": {
"dc-api": {
"command": "/path/to/dc-api/mcp/bin/run.sh"
}
}
}
```

Replace `/path/to/dc-api/mcp` with the absolute path to this directory on your machine.

If you need to override the API base URL or supply a semantic search model ID, pass them as environment variables:

```json
{
"mcpServers": {
"dc-api": {
"command": "/path/to/dc-api/mcp/bin/run.sh",
"env": {
"DC_API_BASE": "https://api.dc.library.northwestern.edu/api/v2",
"DC_IIIF_BASE": "https://iiif.dc.library.northwestern.edu/iiif/3"
}
}
}
}
```

After editing the file, restart Claude Desktop for the changes to take effect. You should see the `dc-api` server listed under the MCP tools panel.

## Tests

There are several ways to invoke the test suite:

| Command | Result |
| ------------------- | ------------------------------------------------------------ |
| `npm run test` | Run the test suite |
| `npm test:watch` | Run the test suite, watching for changes |
| `npm test:coverage` | Run the test suite and calculate coverage |
| `npm test:record` | Run the test suite against live data and record new fixtures |

- By default, the test suite uses pre-recorded HTTP fixtures. You can set `MSW_MODE=live` to run against live data.
- `npm test:record` will record new test fixtures (requires `mitmproxy`, which can be installed with `pip install mitmproxy`).
Loading
Loading