MDEngine

MD workbench for agents: 13 analysis tools, renders, hosted GPU runs; LAMMPS + OpenMM.

Should I use this

Quality & Safety

A
Description quality
100%
Schema completeness
93%
Naming quality
89%
Poisoning risk
100%
Permission match
100%
Protocol compliance
100%

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~2,807Tokens (tool definitions)
~1.1 KBTypical response size
Significant attention impact (2.19% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "mdengine": {
      "url": "https://api.forcefieldsilicon.com/mcp"
    }
  }
}

Remote endpoints

https://api.forcefieldsilicon.com/mcpstreamable-http

What it can do

Tool inventory

Tools (14)

🟢 Read-only🟡 Write🔴 Delete⚪ Unknown
🟢guide(customer_type, template)

No key needed. Without customer_type: the list of guides (one line each), the start page and how to get a key. With customer_type (mineral-processing | dark-proteins): the full guide, which says what to supply, what runs, what comes back and what it costs. With template (openmm-stability): the script text of that template, ready to save and submit.

Input Schema

{
  "type": "object",
  "properties": {
    "customer_type": {
      "type": "string",
      "description": "mineral-processing | dark-proteins; omit for the list"
    },
    "template": {
      "type": "string",
      "description": "openmm-stability (dark-proteins stage 1 OpenMM script); returns the script text"
    }
  }
}
⚪campaign_request(customer_type, question, inputs_available, grid, data_rules, ...)

No key needed. Sends a study request to a person and returns a request_id, the tier that fits, the price band, what we still need from you, the next step and the claim scope. Nothing is run or charged. Call it after reading a guide.

Input Schema

{
  "type": "object",
  "properties": {
    "customer_type": {
      "type": "string",
      "enum": [
        "mineral-processing",
        "dark-proteins",
        "semiconductor",
        "other"
      ],
      "description": "mineral-processing | dark-proteins | semiconductor | other"
    },
    "question": {
      "type": "string",
      "minLength": 20,
      "maxLength": 4000,
      "description": "One paragraph: the decision the study feeds"
    },
    "inputs_available": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "What you can supply now, e.g. bath range, AlphaFold model, ligand list"
    },
    "grid": {
      "type": "string",
      "description": "Free text: compositions x temperatures, or ligands x pockets (e.g. 3 ligands x 1 receptor)"
    },
    "data_rules": {
      "type": "string",
      "description": "How the data and results may be used, kept or shared"
    },
    "contact_email": {
      "type": "string",
      "description": "Where the reply goes"
    },
    "organization": {
      "type": "string",
      "description": "Optional"
    }
  },
  "required": [
    "customer_type",
    "question",
    "contact_email"
  ]
}
🟢account

Balance in USD (`balance_usd`), the part of it held by your unfinished jobs (`reserved_usd`, `held_jobs`) and what a new submit can use (`available_usd` = balance - reserved; a submit needs wall_limit_s x rate of it), how jobs are priced (`pricing.mode` job = the deck's own work in atom-steps at per-class prices, capped at wall_limit_s x rate; metered = per second of pod time), the rate table, the key id of the API key in use, and `packs` (when the endpoint sells credit): [{id, name, usd, gpu_h, url}] to top up THIS key by appending ?client_reference_id=<key_id> to the pack url.

Input Schema

{
  "type": "object",
  "properties": {}
}
🟡submit_job(input, label, gpu, wall_limit_s, estimate_s, ...)

One call: create a hosted GPU job, upload the deck given INLINE as {relative_path: text}, and queue it. Total inline size <= 8 MB; for larger decks use create_job, PUT the tarball to upload_url, then start_job. Billing starts at the first heartbeat (state running) and stops at done/failed/cancelled. The deck is executed as a program on an isolated GPU pod.

Input Schema

{
  "type": "object",
  "properties": {
    "input": {
      "type": "string",
      "description": "Relative path of the LAMMPS (or runner) input script inside the deck, e.g. in.lmp"
    },
    "label": {
      "type": "string",
      "description": "Free text <= 120 chars shown in job lists"
    },
    "gpu": {
      "type": "string",
      "description": "GPU class; call account for the offered classes and how jobs are priced. Default any = cheapest available"
    },
    "wall_limit_s": {
      "type": "integer",
      "description": "Hard cap in seconds (default 14400, max 86400); the job fails at the cap and is billed to it"
    },
    "estimate_s": {
      "type": "integer",
      "description": "Your runtime guess in seconds; informational only; the pre-check uses wall_limit_s net of credit held by your unfinished jobs"
    },
    "runner": {
      "type": "string",
      "description": "Runner flavour: lammps (default) or openmm (beta)"
    },
    "launch": {
      "type": "string",
      "description": "Launch template; omit for the default KOKKOS/CUDA LAMMPS command line"
    },
    "end_marker": {
      "type": "string",
      "description": "Optional line your deck prints when it truly finished (e.g. a `print DONE` at the end); a done job whose log lacks a line starting with it gets verdict=warnings, end_marker_missing=true"
    },
    "files": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      },
      "description": "Deck contents: {\"in.lmp\": \"...\", \"data.al\": \"...\"}; paths relative, no '..'; must include `input`"
    }
  },
  "required": [
    "input",
    "files"
  ]
}
🟡create_job(input, label, gpu, wall_limit_s, estimate_s, ...)

Step 1 of the two-step path for big decks: validates the spec, reserves a job id, returns a presigned upload_url. PUT the deck as a .tar.gz (<= 2 GB, relative paths, input at `input`) to upload_url, then call start_job.

Input Schema

{
  "type": "object",
  "properties": {
    "input": {
      "type": "string",
      "description": "Relative path of the LAMMPS (or runner) input script inside the deck, e.g. in.lmp"
    },
    "label": {
      "type": "string",
      "description": "Free text <= 120 chars shown in job lists"
    },
    "gpu": {
      "type": "string",
      "description": "GPU class; call account for the offered classes and how jobs are priced. Default any = cheapest available"
    },
    "wall_limit_s": {
      "type": "integer",
      "description": "Hard cap in seconds (default 14400, max 86400); the job fails at the cap and is billed to it"
    },
    "estimate_s": {
      "type": "integer",
      "description": "Your runtime guess in seconds; informational only; the pre-check uses wall_limit_s net of credit held by your unfinished jobs"
    },
    "runner": {
      "type": "string",
      "description": "Runner flavour: lammps (default) or openmm (beta)"
    },
    "launch": {
      "type": "string",
      "description": "Launch template; omit for the default KOKKOS/CUDA LAMMPS command line"
    },
    "end_marker": {
      "type": "string",
      "description": "Optional line your deck prints when it truly finished (e.g. a `print DONE` at the end); a done job whose log lacks a line starting with it gets verdict=warnings, end_marker_missing=true"
    }
  },
  "required": [
    "input"
  ]
}
⚪start_job(id)

Step 2: queue a job whose deck tarball has been uploaded. A GPU pod is launched; billing starts when it reports running.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id, e.g. MDJOB-20260907-3F200C"
    }
  },
  "required": [
    "id"
  ]
}
🟢job_status(id)

State (created|uploaded|queued|launching|running|uploading|done|failed|cancelled), GPU, rate, billed seconds, cost so far, exit code, error, last thermo lines, and the post-run verdict: clean | warnings (a done run whose log shows QEq CG failures, lost atoms, a fix halt, or no end_marker line; counts in `warnings`).

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id, e.g. MDJOB-20260907-3F200C"
    }
  },
  "required": [
    "id"
  ]
}
🟢job_log(id)

The last <= 20 thermo/log lines the running pod reported (30 s heartbeat). Full log.lammps is in the results tarball.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id, e.g. MDJOB-20260907-3F200C"
    }
  },
  "required": [
    "id"
  ]
}
🟢job_results(id)

For a done/failed job: a presigned download_url (valid ~7 days) for the results tarball (work/, log.lammps, exitcode). Results are deleted 30 days after the run.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id, e.g. MDJOB-20260907-3F200C"
    }
  },
  "required": [
    "id"
  ]
}
🟢list_jobs(limit, full)

Jobs of this API key, newest first. Compact rows (id, state, label, created, finished, gpu, cost_usd, error) unless full=true.

Input Schema

{
  "type": "object",
  "properties": {
    "limit": {
      "type": "integer",
      "description": "1..200, default 20"
    },
    "full": {
      "type": "boolean",
      "description": "Return the complete status object per job (default false)"
    }
  }
}
🔴delete_results(id)

For a finished job: delete its deck and results tarballs immediately instead of at the automatic 30-day purge. Metadata and billing records are kept; results can no longer be downloaded.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id, e.g. MDJOB-20260907-3F200C"
    }
  },
  "required": [
    "id"
  ]
}
🟢capabilities(runner, full)

Capability manifest of the hosted runners: LAMMPS version, installed packages, and every style by category with gpu=true (KOKKOS-accelerated) or gpu=false (exists, but runs on the pod's CPU cores at the GPU rate). Default = compact summary; runner=lammps&full=true returns the whole style table. Use preflight_deck to check a specific deck.

Input Schema

{
  "type": "object",
  "properties": {
    "runner": {
      "type": "string",
      "description": "lammps | openmm; omit for all"
    },
    "full": {
      "type": "boolean",
      "description": "Include the full style table (large)"
    }
  }
}
🟢preflight_deck(input, files)

Dry run of the check submit_job performs: which styles the deck asks for are MISSING on every hosted LAMMPS image (the run would exit at startup), which are CPU-only, whether its pair style will use the GPU at all, and which image (`runner`) the job will be routed to — decks needing packages beyond the fast default image run on lammps-full automatically. Nothing is created or billed.

Input Schema

{
  "type": "object",
  "properties": {
    "input": {
      "type": "string",
      "description": "Relative path of the LAMMPS (or runner) input script inside the deck, e.g. in.lmp"
    },
    "files": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      },
      "description": "Deck contents {path: text}, must include `input`"
    }
  },
  "required": [
    "input",
    "files"
  ]
}
🔴cancel_job(id)

Cancel a job that is not finished. A running job is billed up to the cancel time; its pod is terminated.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "Job id, e.g. MDJOB-20260907-3F200C"
    }
  },
  "required": [
    "id"
  ]
}

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded14 tools
verifiedversion not recorded14 tools
verifiedversion not recorded14 tools
verifiedversion not recorded12 tools
verifiedversion not recorded12 tools
verifiedversion not recorded12 tools