July 2026 Update:
Since writing the post below, I was able to get more hands-on with Claude Science including:
- Confirming that I can proxy AWS SSM traffic over the native Claude Science SSH connector; allowing access to private AWS HPC resources and compute servers
- Developed a Claude Science skill that can use the SSM proxy method to connect and run Schrodinger compchem jobs on AWS HPC clusters
- Developed a more generic Claude Science skill that can use the SSM proxy method to access Slurm HPC systems inside private AWS environments; this method should work for both AWS Parallelcluster (tested live) and AWS PCS managed HPC service (not tested yet)
All of this has been developed into a public git repo here:
https://github.com/bioteam/claude-science-hpc-integrations
Claude Science Dropped Today – How do I connect it to live compute?
Claude Science, even in beta form, looks pretty interesting. However, unlike my current usage of Claude Code, the “Claude science” bits run in remote sandbox containers. Since my day job involves helping scientists access and use large-scale HPC and IT infrastructure to “get science done,” my first thought was, “How the hell do I connect this to my local GPU and HPC systems?”
This is how I work today using Claude Code via a Claude Teams subscription — even though Code is running locally on my laptop, I still had to wire up some tooling and MCPs in order to allow Claude Code to facilitate my work on designing, architecting, deploying, and (most importantly) testing and troubleshooting HPC systems that run large-scale data-intensive life science workloads.
This is my current setup:
As the diagram makes obvious — Claude is only useful to me when it can:
- Talk to free/published/open MCPs that provide ground truth documentation for things I work with constantly like
https://awslabs.github.io/mcp/servers/aws-knowledge-mcp-server - Talk to a custom MCP/RAG that I’ve stuffed full of HPC, Vendor Docs, Scientific Application Docs and internal consulting “lessons-learned” details
https://hpc-mcp.apps.bioteam.cloud/ - Connect securely and efficiently (without wasting tokens) to a lot of remote systems using a ton of different access methods and transport schemes
What can Claude Science (natively) connect to today?
Note: Claude Science literally dropped today and is still in beta. It is super likely this blog post is going to be obsolete relatively quickly. I’ll document any changes or updates I make to this doc over time.
Claude Science reaches remote compute through three native provider families — (1) SSH/scheduler clusters, (2) the Modal managed-API backend, and (3) managed model endpoints — all driven by a uniform submit → wait → harvest job lifecycle, plus a separate connector (MCP) plane for read/lookup and for transports the job lifecycle can’t express. There is no interactive remote shell; every remote computation is a job with approvals, input staging, and output harvesting.
Connectors: Claude Code vs Claude Science
Connectors are how Claude Science connects to remote services (rather than running batch jobs). This is the surface most relevant to adapting your own MCP servers.
The model differs from Claude Code. In Claude Code a custom MCP is launched by the client (usually stdio) and its tools appear directly in the model’s tool list. In Claude Science a connected MCP is:
- Registered as a connector (Settings → Connectors), not spawned from a local config file. Remote/HTTP transports (SSE or streamable-HTTP) are the natural fit; a
stdio-only server must be exposed over HTTP or wrapped. - Called programmatically:
host.mcp("<server>", "<tool>", **kwargs)— from therepltool only. Results are parsed JSON; hand them to analysis code via./handoff/<name>.json. - Gated by auth state:
authorized/not-required/unauthorized.host.mcp()can only reach a connected server.
Discovering a connector’s tools: search_skills({prefix:"mcp-"}) lists every connected server (each gets an auto-generated mcp-<server> method-reference skill); or, from repl, host.agents.list_connectors("<server>") returns tools:[{name, description}].
How can I bring my Claude Code resources into Claude Science?
I started going down this road shortly after downloading and firing up the beta product. What it boills down to is this:
- Claude Science can connect to external MCPs so if you have live running things that are useful, you can import them into the Claude Science environment
- Claude Science can connect to local MCP servers running on your laptop or endpoint so if you have local MCPs, then Claude Science can be made aware of them
- If you have admin access to Claude Teams or Claude Enterprise, you can
- Centrally register and authorize third-party or your own hosted/custom MCPs
- You can package up “Claude Science Skills” and make them available to other Claude Science users in your organization or teams
Given my setup and daily tools, I’m taking the approach of just connecting in my “daily driver” MCPs so I can access them within the Claude Science context. Since I’m also an admin for our Claude Teams subscription, I can also centrally authorize MCPs, custom connections, and other skills as needed. Stay tuned, as we’ll write about this as we deploy it…
What Claude Science Natively Supports TODAY
Note: I will try to keep this post updated as a beta product like Claude Science is likely to be updated and enhanced very quickly
However, as an HPC/Infrastructure person who supports scientists who are likely going to be using this tool ASAP, I needed to understand fast what it could do out of the box when it comes to connecting the hosted “science” platform to compute resources belonging to or accessible to the local users.
This is what I’ve found so far — yes I had Claude Science dump it’s own capabilities, heh:
1. The claude science mental model: two planes
The single most important fact:
Claude Science splits work across two kinds of kernel, and the plane a call lives in determines whether it exists at all.

| Plane | Tool(s) | Remote-compute surface that lives here |
|---|---|---|
| Data kernel | python / r / bash |
Preparing job inputs; host.artifacts, host.lineage, host.llm. No host.compute, no host.mcp. |
| Control plane | repl |
host.compute.* (jobs), host.mcp(...) (connectors), host.model_endpoints.*, host.query, host.frames, host.agents.*, host.skills.*. |
Plus two specialized tools (not kernels) used for managed providers:
compute_provider— a confined shell with a managed-API provider’s SDK pre-authenticated (used to build images / hydrate weight volumes for Modal, and to run inference cells against managed model endpoints).list_compute/compute_details/ask_about_compute— discovery and durable per-host state.
Why the split exists: job submission opens the SSH connection and the user’s approval modal from the orchestrator’s own process — outside the sandboxed data workspace. So host.compute is deliberately not attached in the python tool (you’d get host has no method 'compute'). The two kernels share the workspace directory but not memory — you pass data between them through files (e.g. ./handoff/result.json).
2. The provider taxonomy (what stuff you can connect to)
Everything reachable natively falls into one of four buckets. The first three are compute providers surfaced by list_compute; the fourth is the connector plane, which is orthogonal.

2.1 SSH / scheduler clusters — ssh:<name>
The primary HPC path. The user registers a host in Settings → Compute (hostname, user, key, and whatever connection fields that form exposes); it then appears to the agent as ssh:<name>. (Exactly which connection options the form accepts — jump host, ProxyCommand, ~/.ssh/config reuse — is not documented in the native skills; see the unverified note below.)
- Schedulers natively understood: Slurm (
#SBATCH), PBS/Torque (#PBS), LSF (#BSUB), andnone(direct exec on a login node / standalone box). Scheduler directives are written at the top of the job script and the platform hoists them into the dispatch wrapper. - Multi-cluster: each cluster is its own provider (
ssh:frontera,ssh:perlmutter, …). They share nothing; each carries its own durablecompute_detailsdoc.
2.2 Managed-API backend (BYOC) — byoc:modal
GPU/CPU jobs run in the user’s own Modal account (their workspace, their bill), dispatched with host.compute.create('byoc:modal', ...). Hardware is named in plain terms (gpu='A100', cpu, memory, timeout). This is the native path to on-demand GPUs without having to stand up a cluster.
- Two approval cards (rather than one) because it spends the user’s credentials: a one-time kernel card for env setup, and a tier card on the first job.
- Environment setup happens in the
compute_providertool:list_envs()/build_env(name)build container images and hydrate weight Volumes on Modal’s own network. The returnedim-…image reference is recorded incompute_detailsfor warm reuse. - GPU tiers:
A10G(24 GB),A100(40 GB),A100-80GB,H100(80 GB).
Scope note.
compute-env-setupdescribes managed-API providers generically and names GCP and RunPod as anticipated shapes, but Modal is the only managed-API backend with a shipped adapter and abyoc:provider string today (byoc:modal). Treat GCP/RunPod as “the architecture anticipates them,” not “available now.” Ifcompute.create('byoc:modal', …)returnsunknown provider, Modal isn’t enabled in that install (Settings → Compute → Modal).
2.3 Managed model endpoints
A model service the daemon owns — for inference, not general batch jobs. Registered once with host.model_endpoints.register(...); thereafter the daemon brings the model up on demand, swaps models on the device one at a time, and runs your inference cells. Two modes (the user picks one per machine under Customize → Compute → Model endpoints):
- Local — a model-server container the daemon starts/stops on demand (you compose idempotent start/stop scripts; the credential is a registry pull key that never enters your kernel).
- Remote — an upstream HTTPS model API (no lifecycle scripts; cells are plain HTTP clients of a preloaded
BASE_URL, authenticating with$INFER_API_KEY).
Endpoints are not kernel environments — you call them from the compute_provider tool with the endpoint’s registered name; BASE_URL is preloaded into the cell.
2.4 Connectors (MCP) — the orthogonal plane
Not compute, but the other native way to reach remote services. A connected MCP server is called programmatically as host.mcp("server", "tool", **kwargs) from the repl tool (never a python/r cell), returns parsed JSON, and is gated by auth state (authorized / not-required / unauthorized). Covered in §6 because it’s central to custom-connector development.
3. The job lifecycle — submit → wait → harvest
There is no interactive remote shell. Every remote computation on an SSH or Modal provider is the same four beats. The kernel never blocks on a job (jobs can run for hours); you submit, park, and the daemon’s poller harvests outputs and notifies you.

The canonical pattern:




Input staging (inputs=):
| Form | Meaning |
|---|---|
{"src": "path", "dst_filename": "name.dat"} |
staged from workspace → appears as ./name.dat in the job cwd |
{"src": "{{artifact:<id>}}", "dst_filename": "ref.dat"} |
stage an artifact |
{"remote_path": "/scratch/.../big.dat"} |
already on the host → symlinked, no transfer (use for >~100 MB) |
dst_filename is a bare filename — no /, rejected at submit. Modal inputs are stream-staged and capped at 1 GiB per submit (use a Volume above that); SSH inputs use {remote_path} for large host-resident files.
Output harvesting (outputs=):
| Form | Meaning |
|---|---|
"*.pdb" or {"glob":..., "visibility":"featured"} |
featured deliverable |
{"glob":"*.log", "visibility":"hidden"} |
harvested but not featured (diagnostics) |
{"glob":..., "residency":"remote"} |
stays on the host, returned as left_on_remote (for chaining) |
Only files under the job cwd are harvested (flatten subdir output with cp ./out/*.ext ./). Harvest caps at ~100 MB/file; larger outputs stay remote unless you raise harvest:{max_file_mb:...} or set residency:"remote".
Fan-out: there is no --array — submit one job per task; the poller tracks them all and posts one compute_done each. Loop wait_for_notification, iterating its notifications list (several jobs may finish at once); the loop ends when it returns {status:"error"} (no jobs remain).
Concurrency budget: host.compute.set_concurrency_limit(k) binds a ceiling across all sub-agents in the session (the daemon holds submits over k). host.compute.status() shows your k and the provider’s own ceiling — set k at or below the provider ceiling, which refuses rather than queues.
Approval budget: each non-Always-Allowed submit_job/call_command shows one modal, max 10 per turn — batch fan-out into job scripts or have the user click “Always Allow.”
4. The native SDK surface (quick reference)
All of these are control-plane (repl tool) or specialized-tool calls.
host.compute — the job surface (SSH and Modal)
| Call | Purpose |
|---|---|
host.compute.create("ssh:<name>") / create("byoc:modal", provider_params={...}) |
bind a provider handle (stateless; container/connection created on first submit_job) |
c.submit_job(intent=, command=, inputs=[], outputs=[], timeout_seconds=) |
submit one job; returns immediately |
c.call_command(cmd, intent=, login_shell=) |
run a short command (SSH only — discovery/probing; bails on a byoc: handle) |
c.attach_job(job_id).result() |
non-blocking read of the harvested result dict (output_files, stdout_tail, left_on_remote, …) |
c.download("/abs/path") |
pull any readable host file (SSH only; approval card outside scratch) |
c.close() |
clean up the remote workdir / tear down the warm Modal container |
host.compute.set_concurrency_limit(k) / .status() |
session-wide concurrency budget |
compute_provider tool — Modal env setup & endpoint inference
| Call | Purpose |
|---|---|
list_envs() |
enumerate bundled Modal env definitions (packages, GPU tier, secrets) |
build_env(name, hydrate=False) |
build the image / hydrate weight Volume; returns {image:'im-…', spec_sha, volumes, ...} |
compute_provider_config() |
report the bound Modal Environment / app / egress mode for this kernel |
host.model_endpoints — managed model endpoints
| Call | Purpose |
|---|---|
host.model_endpoints.free_port() |
allocate a loopback port (local mode only) |
host.model_endpoints.register(name=, url=, credential=, skill=, start=, stop=, live=) |
register an endpoint once (cards the user) |
host.mcp — connectors (§6)
host.mcp("server", "tool", **kwargs) → parsed JSON (control plane only).
Discovery & durable state (brain tools)
| Tool | Purpose |
|---|---|
list_compute |
what providers are registered right now (live — the user can add/enable hosts mid-session) |
compute_details(provider, mode="read"/"append"/"replace") |
the only per-host state that survives across sessions |
ask_about_compute(provider, question) |
ask the user the facts no probe can discover (account string, preferred env, install permission) |
5. How a host becomes usable (registration & discovery)

- Registration is a user action. The agent cannot add a compute provider — the user adds the host (or enables Modal) in Settings → Compute. After that,
list_computereturns it and the agent can drive it. - First contact: read
compute_details→ if it’s a bare## Resourcesheader, spend one batchedc.call_command(...)probe (identity, partitions, modules, conda envs, scratch) and oneask_about_computefor what only the user knows, then record a baseline block. compute_detailsscope: visible to every future session on that host, across all projects. Record only what’s true of the host/provider (partition, account, activation lines, gotchas) — tag each lineverified/per user/untested. Project results and per-job state do not belong there (those go to artifacts).
Where durable state lives
| State | Lives in | Survives sessions? |
|---|---|---|
| Per-host facts (partition, account, env, gotchas) | compute_details(provider) |
yes (all projects) |
| Job outputs | artifacts (save_artifacts) |
yes (project) |
| Reproducible workflows / helper code | skills | yes (catalog) |
| In-kernel variables, workspace files | kernel / workspace | no (swept after idle) |
7. At-a-glance comparison
| SSH / scheduler cluster | Modal (byoc:modal) |
Managed model endpoint | Connector (MCP) | |
|---|---|---|---|---|
| Provider string | ssh:<name> |
byoc:modal |
registered name | connector name |
| What it’s for | batch jobs on your HPC | on-demand GPU/CPU containers | model inference services | remote services / lookup / exec-where-SSH-impossible |
| Driven by | host.compute + lifecycle |
host.compute + lifecycle |
host.model_endpoints + compute_provider |
host.mcp (repl) |
| Schedulers | Slurm / PBS / LSF / none | n/a (Modal hardware terms) | n/a | n/a |
| Approvals | 1 modal/job | 2 cards (kernel + tier) | 1 registration card | connect-time auth |
| Input staging / harvest | yes (inputs=/outputs=) |
yes (≤1 GiB inputs; Volumes above) | n/a (HTTP I/O) | you handle it |
| Output provenance | artifacts + lineage | artifacts + lineage | n/a | none |
| Registration | user, Settings → Compute | user, Settings → Compute | register() (cards user) |
user, Settings → Connectors |
| Non-SSH transports | plain SSH only confirmed; Tailscale/SSM unverified (§2.1) | n/a | n/a | the fallback for non-SSH exec |
Reference basis: the native Claude Science compute/connector surfaces as documented in the remote-compute-ssh, remote-compute-modal, compute-env-setup, managed-model-endpoints, and using-model-endpoint skills (all origin: anthropic), plus the host.compute / host.mcp / compute_details SDK. Excludes any personal skills or connectors. list_compute in the authoring session returned zero registered providers — the capabilities above are the platform baseline, not a description of any currently-connected host.





