Skip to content

Commit d7cfb0b

Browse files
committed
Add stateless MCP server to API
Use @nulib/clover-mcp for MCP UI resource Add view-search-results tool Combine search and semantic-search tools Add source maps to MCP Add MCP tests Update to use new visibility / auth filtering in DCAPI
1 parent 3eef8c7 commit d7cfb0b

41 files changed

Lines changed: 13359 additions & 23 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/test-node.yml

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,41 @@ on:
55
- ".github/workflows/test-node.yml"
66
- "api/**"
77
workflow_dispatch:
8-
defaults:
9-
run:
10-
working-directory: ./api
118
jobs:
12-
test:
9+
test-api:
1310
runs-on: ubuntu-latest
11+
defaults:
12+
run:
13+
working-directory: ./api
1414
env:
1515
AWS_ACCESS_KEY_ID: ci
1616
AWS_SECRET_ACCESS_KEY: ci
1717
steps:
1818
- uses: actions/checkout@v3
1919
- uses: actions/setup-node@v3
2020
with:
21-
node-version: 20.x
21+
node-version: 24.x
2222
cache: "npm"
23-
cache-dependency-path: 'api/package-lock.json'
23+
cache-dependency-path: "api/package-lock.json"
2424
- run: npm ci
2525
- name: Check code style
2626
run: npm run lint && npm run prettier
2727
- name: Run tests
2828
run: npm run test:coverage
2929
- name: Validate OpenAPI spec
3030
run: npm run validate-spec
31+
test-mcp:
32+
runs-on: ubuntu-latest
33+
defaults:
34+
run:
35+
working-directory: ./mcp
36+
steps:
37+
- uses: actions/checkout@v3
38+
- uses: actions/setup-node@v3
39+
with:
40+
node-version: 24.x
41+
cache: "npm"
42+
cache-dependency-path: "mcp/package-lock.json"
43+
- run: npm ci
44+
- name: Run tests
45+
run: npm run test:coverage

.tool-versions

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
nodejs 20.15.0
2-
java corretto-19.0.1.10.1
1+
nodejs 24.11.1
2+
java corretto-19.0.1.10.1
33
aws-sam-cli 1.148.0
4-
python 3.12.2
5-
uv 0.9.5
4+
python 3.12.2
5+
uv 0.9.5

Makefile

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ help:
2828
echo "make serve-https | run the SAM server locally (HTTPS on port 3002)"
2929
echo "make style-node | run node code style check"
3030
echo "make style-python | run python code style check"
31+
echo "make test-mcp | run mcp tests"
3132
echo "make test-node | run node tests"
3233
echo "make test-python | run python tests"
3334
echo "make cover-node | run node tests with coverage"
@@ -68,7 +69,14 @@ deps-api:
6869
deps-av-download:
6970
cd av-download/lambdas ;\
7071
npm list >/dev/null 2>&1 || npm ci
71-
deps-node: deps-api deps-av-download
72+
deps-mcp:
73+
cd mcp ;\
74+
npm list >/dev/null 2>&1 ;\
75+
deps=$$? ;\
76+
test $$deps -eq 0 || npm ci
77+
test-mcp: deps-mcp
78+
cd mcp && npm test
79+
deps-node: deps-api deps-av-download deps-mcp
7280
cover-node: deps-node
7381
cd api && npm run test:coverage
7482
style-node: deps-node

api/src/package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/template.yaml

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Description: dc-api-v2 API
1313
Globals:
1414
Function:
1515
CodeUri: ./src
16-
Runtime: nodejs20.x
16+
Runtime: nodejs24.x
1717
Architectures:
1818
- x86_64
1919
MemorySize: 128
@@ -118,9 +118,9 @@ Parameters:
118118
Conditions:
119119
CustomConfigSecret:
120120
Fn::Not:
121-
- Fn::Equals:
122-
- !Ref ApiConfigPrefix
123-
- ""
121+
- Fn::Equals:
122+
- !Ref ApiConfigPrefix
123+
- ""
124124
DeployAPI:
125125
Fn::Equals: [!Ref DeployAPI, "true"]
126126
DeployAVDownload:
@@ -129,8 +129,8 @@ Conditions:
129129
Fn::Equals: [!Ref DeployChat, "true"]
130130
WriteSecret:
131131
Fn::Equals:
132-
- !Ref WriteConfigSecret
133-
- true
132+
- !Ref WriteConfigSecret
133+
- true
134134
Resources:
135135
#* apiDependencies:
136136
#* Type: AWS::Serverless::LayerVersion
@@ -148,7 +148,7 @@ Resources:
148148
Type: AWS::SecretsManager::Secret
149149
Condition: WriteSecret
150150
Properties:
151-
Name:
151+
Name:
152152
Fn::If:
153153
- CustomConfigSecret
154154
- !Sub "${ApiConfigPrefix}/config/dcapi"
@@ -471,10 +471,10 @@ Resources:
471471
Type: AWS::Serverless::Function
472472
Properties:
473473
Handler: handlers/get-provider-capabilities.handler
474-
Description: boolean to indicate whether auth provider currently supports feature
474+
Description: boolean to indicate whether auth provider currently supports feature
475475
#* Layers:
476476
#* - !Ref apiDependencies
477-
Environment:
477+
Environment:
478478
Variables:
479479
PROVIDER_CAPABILITIES: !Ref ProviderCapabilities
480480
Policies:
@@ -740,6 +740,28 @@ Resources:
740740
ApiId: !Ref dcApi
741741
Path: /oai
742742
Method: POST
743+
mcpFunction:
744+
Type: AWS::Serverless::Function
745+
Properties:
746+
CodeUri: ../mcp
747+
Handler: mcp/lambda.handler
748+
Runtime: nodejs24.x
749+
Environment:
750+
Variables:
751+
SECRETS_PATH: !Ref SecretsPath
752+
Timeout: 30
753+
MemorySize: 256
754+
Policies:
755+
- !Ref SecretsPolicy
756+
Events:
757+
ApiEvent:
758+
Type: HttpApi
759+
Properties:
760+
ApiId: !Ref dcApi
761+
Path: /mcp
762+
Method: any
763+
Metadata:
764+
BuildMethod: makefile
743765
chatWebsocketEndpoint:
744766
Type: AWS::Serverless::Function
745767
Condition: DeployChat
@@ -749,8 +771,8 @@ Resources:
749771
#* Layers:
750772
#* - !Ref apiDependencies
751773
Environment:
752-
Variables:
753-
WEBSOCKET_URI: !Ref ChatWebSocketURI
774+
Variables:
775+
WEBSOCKET_URI: !Ref ChatWebSocketURI
754776
Policies:
755777
- !Ref SecretsPolicy
756778
Events:
@@ -794,7 +816,7 @@ Resources:
794816
Path: /chat/feedback
795817
Method: POST
796818
chatFeedbackBucket:
797-
Type: 'AWS::S3::Bucket'
819+
Type: "AWS::S3::Bucket"
798820
chatFeedbackTopic:
799821
Type: AWS::SNS::Topic
800822
Properties:

av-download/lambdas/package-lock.json

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mcp/Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
build:
2+
rm -rf node_modules
3+
npm ci
4+
npm run build
5+
6+
build-mcpFunction: build
7+
cp -r dist/apps/* apps/mcp/package.json $(ARTIFACTS_DIR)

mcp/README.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# dc-api-mcp
2+
3+
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.
4+
5+
## Requirements
6+
7+
- Node.js 24+ (see [.tool-versions](.tool-versions))
8+
- [mise](https://mise.jdx.dev/) (used by `bin/run.sh` to activate the correct runtime)
9+
10+
## Setup
11+
12+
```bash
13+
npm install
14+
```
15+
16+
## Configuration
17+
18+
The server reads the following environment variables:
19+
20+
| Variable | Default | Description |
21+
| -------------- | ------------------------------------------------- | -------------------------------------------------------------------- |
22+
| `DC_API_BASE` | `https://api.dc.library.northwestern.edu/api/v2` | Base URL for the Digital Collections API |
23+
| `DC_IIIF_BASE` | `https://iiif.dc.library.northwestern.edu/iiif/3` | Base URL for the Digital Collections API |
24+
| `SECRETS_PATH` | _(none)_ | The base secrets path to load configuration from AWS Secrets Manager |
25+
26+
## Running locally
27+
28+
### stdio (for Claude Desktop / Claude Code)
29+
30+
```bash
31+
cd src
32+
npm run stdio
33+
```
34+
35+
Or via the wrapper script:
36+
37+
```bash
38+
bin/run.sh
39+
```
40+
41+
### HTTP (Streamable HTTP transport, port 3000)
42+
43+
```bash
44+
cd src
45+
npm run http
46+
```
47+
48+
## Configuring Claude Desktop
49+
50+
Add the following entry to your Claude Desktop configuration file.
51+
52+
**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
53+
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
54+
55+
```json
56+
{
57+
"mcpServers": {
58+
"dc-api": {
59+
"command": "/path/to/dc-api/mcp/bin/run.sh"
60+
}
61+
}
62+
}
63+
```
64+
65+
Replace `/path/to/dc-api/mcp` with the absolute path to this directory on your machine.
66+
67+
If you need to override the API base URL or supply a semantic search model ID, pass them as environment variables:
68+
69+
```json
70+
{
71+
"mcpServers": {
72+
"dc-api": {
73+
"command": "/path/to/dc-api/mcp/bin/run.sh",
74+
"env": {
75+
"DC_API_BASE": "https://api.dc.library.northwestern.edu/api/v2",
76+
"DC_IIIF_BASE": "https://iiif.dc.library.northwestern.edu/iiif/3"
77+
}
78+
}
79+
}
80+
}
81+
```
82+
83+
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.
84+
85+
## Tests
86+
87+
There are several ways to invoke the test suite:
88+
89+
| Command | Result |
90+
| ------------------- | ------------------------------------------------------------ |
91+
| `npm run test` | Run the test suite |
92+
| `npm test:watch` | Run the test suite, watching for changes |
93+
| `npm test:coverage` | Run the test suite and calculate coverage |
94+
| `npm test:record` | Run the test suite against live data and record new fixtures |
95+
96+
- By default, the test suite uses pre-recorded HTTP fixtures. You can set `MSW_MODE=live` to run against live data.
97+
- `npm test:record` will record new test fixtures (requires `mitmproxy`, which can be installed with `pip install mitmproxy`).

0 commit comments

Comments
 (0)