automd-mcp 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.js +66 -31
  2. package/package.json +41 -40
  3. package/LICENSE.md +0 -60
package/dist/index.js CHANGED
@@ -40506,6 +40506,16 @@ var api = {
40506
40506
  body: JSON.stringify(data)
40507
40507
  }),
40508
40508
  deleteProject: (id) => request(`/api/projects/${id}`, { method: "DELETE" }),
40509
+ // Tags
40510
+ getTags: (projectId) => {
40511
+ const query = new URLSearchParams();
40512
+ if (projectId) query.set("projectId", projectId);
40513
+ return request(`/api/tags?${query.toString()}`);
40514
+ },
40515
+ updateInstanceTags: (tags) => request("/api/tags", {
40516
+ method: "PUT",
40517
+ body: JSON.stringify({ tags })
40518
+ }),
40509
40519
  // Health
40510
40520
  health: () => request("/api/health")
40511
40521
  };
@@ -40524,7 +40534,7 @@ function errorResponse(err) {
40524
40534
  function registerTools(server2) {
40525
40535
  server2.registerTool("list_items", {
40526
40536
  title: "List Items",
40527
- description: "List all items (boards, checklists, and pages) with their task counts"
40537
+ description: "List all items (boards, checklists, pages, and knowledge bases) with their task counts. Returns array of {id, name, itemType, projectId, taskCount}."
40528
40538
  }, async () => {
40529
40539
  try {
40530
40540
  const items = await api.listFiles();
@@ -40535,8 +40545,8 @@ function registerTools(server2) {
40535
40545
  });
40536
40546
  server2.registerTool("get_item", {
40537
40547
  title: "Get Item",
40538
- description: "Get an item (board, checklist, or page) with its columns and tasks",
40539
- inputSchema: { itemId: external_exports.string().describe("The item ID") }
40548
+ description: "Get an item (board, checklist, page, or knowledge base) with its columns and tasks",
40549
+ inputSchema: { itemId: external_exports.string().describe("The item ID (obtain from list_items)") }
40540
40550
  }, async ({ itemId }) => {
40541
40551
  try {
40542
40552
  const item = await api.getFile(itemId);
@@ -40559,11 +40569,11 @@ function registerTools(server2) {
40559
40569
  });
40560
40570
  server2.registerTool("create_item", {
40561
40571
  title: "Create Item",
40562
- description: "Create a new board, checklist, or page. Boards use # (H1) for columns and ## (H2) for tasks. Checklists use ## (H2) with [ ]/[x] prefixes. Pages are free-form markdown for knowledge, specs, and documentation. All support YAML frontmatter, plain paragraphs (description), blockquotes (>) for acceptance criteria, and GFM checkboxes for subtasks.",
40572
+ description: "Create a new board, checklist, page, or knowledge base. Boards use # (H1) for columns and ## (H2) for tasks. Checklists use ## (H2) with [ ]/[x] prefixes. Pages are free-form markdown. Knowledge bases are structured collections of entries (## H2) without checkboxes or progress \u2014 ideal for decisions, patterns, and reference material. All support YAML frontmatter, descriptions, blockquotes (>) for acceptance criteria, and GFM checkboxes for subtasks.",
40563
40573
  inputSchema: {
40564
40574
  name: external_exports.string().describe("Name for the new item"),
40565
- itemType: external_exports.enum(["board", "checklist", "page"]).optional().describe("Type of item to create: board (kanban columns), checklist (task list with checkboxes), or page (free-form markdown for knowledge and documentation). Defaults to board"),
40566
- markdown: external_exports.string().optional().describe("Initial markdown content. Start with YAML frontmatter (board:, description:). Use # for columns, ## for tasks. Paragraphs = description, blockquotes (>) = acceptance criteria, checkboxes = subtasks"),
40575
+ itemType: external_exports.enum(["board", "checklist", "page", "knowledge"]).optional().describe("Type of item to create: board (kanban columns), checklist (task list with checkboxes), page (free-form markdown), or knowledge (structured entries without checkboxes/progress). Defaults to board"),
40576
+ markdown: external_exports.string().optional().describe("Initial markdown content. Omit for an empty item. For boards: use # for columns, ## for tasks. For checklists: ## with [ ] prefix. For pages/knowledge: free-form markdown. All types support YAML frontmatter (board:, description:, vocabulary:)."),
40567
40577
  projectId: external_exports.string().optional().describe("Project ID to add the item to (optional)")
40568
40578
  }
40569
40579
  }, async ({ name, itemType, markdown, projectId }) => {
@@ -40605,10 +40615,10 @@ function registerTools(server2) {
40605
40615
  });
40606
40616
  server2.registerTool("add_task", {
40607
40617
  title: "Add Task",
40608
- description: "Add a new task (H2 heading) to a column. Content supports inline metadata like @user #label priority:high due:2025-03-20 est:4h",
40618
+ description: "Add a new task (## H2 heading) to a column. Content supports inline metadata: @user #label priority:high|medium|low due:YYYY-MM-DD est:4h knowledge:true. Do not include built-by: manually \u2014 use the agentName parameter. Call list_tags to discover existing labels before inventing new ones.",
40609
40619
  inputSchema: {
40610
40620
  itemId: external_exports.string().describe("The item ID"),
40611
- columnId: external_exports.string().describe("The column/heading ID to add the task to"),
40621
+ columnId: external_exports.string().describe("The column ID (found in get_item response columns[].id)"),
40612
40622
  content: external_exports.string().describe("Task content with optional inline metadata"),
40613
40623
  agentName: external_exports.string().regex(/^[\w-]+$/).optional().describe("Name of the agent making this change (tagged as built-by)")
40614
40624
  }
@@ -40623,10 +40633,10 @@ function registerTools(server2) {
40623
40633
  });
40624
40634
  server2.registerTool("update_task", {
40625
40635
  title: "Update Task",
40626
- description: "Update a task's content",
40636
+ description: "Update a task's title/content text only. For metadata use update_task_metadata, for completion use toggle_task, for position use move_task, for AC use update_acceptance_criteria, for learnings use update_learnings.",
40627
40637
  inputSchema: {
40628
40638
  itemId: external_exports.string().describe("The item ID"),
40629
- taskId: external_exports.string().describe("The task ID"),
40639
+ taskId: external_exports.string().describe("The task ID (found in get_item response columns[].tasks[].id)"),
40630
40640
  content: external_exports.string().optional().describe("New task content"),
40631
40641
  agentName: external_exports.string().regex(/^[\w-]+$/).optional().describe("Name of the agent making this change (tagged as built-by)")
40632
40642
  }
@@ -40647,7 +40657,7 @@ function registerTools(server2) {
40647
40657
  });
40648
40658
  server2.registerTool("toggle_task", {
40649
40659
  title: "Toggle Task",
40650
- description: "Toggle a task between checked and unchecked",
40660
+ description: "Toggle a task between checked [ ] and unchecked [x]. Only applies to tasks with checkbox prefixes. Sets completedAt on check, clears on uncheck.",
40651
40661
  inputSchema: {
40652
40662
  itemId: external_exports.string().describe("The item ID"),
40653
40663
  taskId: external_exports.string().describe("The task ID")
@@ -40667,7 +40677,7 @@ function registerTools(server2) {
40667
40677
  itemId: external_exports.string().describe("The item ID"),
40668
40678
  taskId: external_exports.string().describe("The task ID"),
40669
40679
  targetColumnId: external_exports.string().describe("Target column ID"),
40670
- targetIndex: external_exports.number().describe("Position in the target column (0-based)")
40680
+ targetIndex: external_exports.number().describe("Position in target column (0-based). Use 0 to place at top. To append, use the column task count from get_item.")
40671
40681
  }
40672
40682
  }, async ({ itemId, taskId, targetColumnId, targetIndex }) => {
40673
40683
  try {
@@ -40698,7 +40708,7 @@ function registerTools(server2) {
40698
40708
  });
40699
40709
  server2.registerTool("add_column", {
40700
40710
  title: "Add Column",
40701
- description: "Add a new column (H1 heading) to an item",
40711
+ description: 'Add a new column (# H1 heading) to a board or checklist. Columns group tasks into workflow stages like "To Do", "In Progress", "Done".',
40702
40712
  inputSchema: {
40703
40713
  itemId: external_exports.string().describe("The item ID"),
40704
40714
  title: external_exports.string().describe("Column title")
@@ -40750,7 +40760,7 @@ function registerTools(server2) {
40750
40760
  });
40751
40761
  server2.registerTool("update_task_metadata", {
40752
40762
  title: "Update Task Metadata",
40753
- description: "Update a task's metadata (priority, assignees, labels, due date, estimate) without rewriting its content",
40763
+ description: "Update a task's metadata (priority, assignees, labels, due date, estimate) without rewriting its content. Call list_tags to discover existing labels before adding new ones.",
40754
40764
  inputSchema: {
40755
40765
  itemId: external_exports.string().describe("The item ID"),
40756
40766
  taskId: external_exports.string().describe("The task ID"),
@@ -40834,7 +40844,9 @@ function registerTools(server2) {
40834
40844
  targetColumnId: external_exports.string().optional().describe("Target column (for move)"),
40835
40845
  targetIndex: external_exports.number().optional().describe("Target index (for move)"),
40836
40846
  displayContent: external_exports.string().optional().describe("Display content (for updateMetadata)"),
40837
- metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe("Metadata fields (for updateMetadata)")
40847
+ metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe("Metadata fields (for updateMetadata)"),
40848
+ acceptanceCriteria: external_exports.string().nullable().optional().describe("Acceptance criteria text (for updateAcceptanceCriteria). Pass null to remove."),
40849
+ learnings: external_exports.string().nullable().optional().describe("Learnings text (for updateLearnings). Pass null to remove.")
40838
40850
  })).describe("Array of task updates to apply")
40839
40851
  }
40840
40852
  }, async ({ itemId, agentName, updates }) => {
@@ -40869,7 +40881,7 @@ function registerTools(server2) {
40869
40881
  });
40870
40882
  server2.registerTool("search_tasks", {
40871
40883
  title: "Search Tasks",
40872
- description: "Search for tasks across all items by text, assignee, label, or status",
40884
+ description: "Search for tasks across all items by text, assignee, label, or status. Use list_tags to discover valid label values.",
40873
40885
  inputSchema: {
40874
40886
  query: external_exports.string().optional().describe("Text to search for in task content"),
40875
40887
  assignee: external_exports.string().optional().describe("Filter by assignee (without @)"),
@@ -40913,7 +40925,7 @@ function registerTools(server2) {
40913
40925
  });
40914
40926
  server2.registerTool("search_context", {
40915
40927
  title: "Search Context",
40916
- description: 'Search for institutional knowledge across all items. Searches task descriptions, acceptance criteria, and learnings \u2014 not just titles. Use this to find relevant context before starting work on a task (e.g. "what do we know about auth?" or "what was learned about pricing?").',
40928
+ description: "Search for contextual detail (descriptions, acceptance criteria, learnings) across all items. Returns any task with rich content \u2014 broader than find_knowledge which only returns knowledge:true items. Use this for finding implementation details, past decisions, and context before starting work. Use list_tags to discover valid label values.",
40917
40929
  inputSchema: {
40918
40930
  query: external_exports.string().optional().describe("Text to search for across descriptions, AC, learnings, and task content"),
40919
40931
  label: external_exports.string().optional().describe("Filter by label (without #). Also matches #tags inside learnings text."),
@@ -40934,14 +40946,18 @@ function registerTools(server2) {
40934
40946
  task.content,
40935
40947
  task.description,
40936
40948
  task.acceptanceCriteria,
40937
- task.learnings
40949
+ task.learnings,
40950
+ ...item.meta?.tags ?? []
40938
40951
  ].filter(Boolean).join(" ").toLowerCase();
40939
40952
  let match = true;
40940
40953
  if (q && !searchable.includes(q)) match = false;
40941
40954
  if (label) {
40942
40955
  const hasLabel = task.metadata.labels.includes(label);
40943
40956
  const hasInlineLabelTag = searchable.includes(`#${label.toLowerCase()}`);
40944
- if (!hasLabel && !hasInlineLabelTag) match = false;
40957
+ const hasFrontmatterTag = item.meta?.tags?.some(
40958
+ (t) => t.toLowerCase() === label.toLowerCase()
40959
+ );
40960
+ if (!hasLabel && !hasInlineLabelTag && !hasFrontmatterTag) match = false;
40945
40961
  }
40946
40962
  const hasContext = task.description || task.acceptanceCriteria || task.learnings;
40947
40963
  if (!hasContext) match = false;
@@ -40972,7 +40988,7 @@ function registerTools(server2) {
40972
40988
  });
40973
40989
  server2.registerTool("list_projects", {
40974
40990
  title: "List Projects",
40975
- description: "List all projects"
40991
+ description: "List all projects with their curated tags. Returns array of {id, name, color, tags}. Use project id as projectId in create_item, get_project_items, or list_tags."
40976
40992
  }, async () => {
40977
40993
  try {
40978
40994
  const projects = await api.listProjects();
@@ -41013,9 +41029,23 @@ function registerTools(server2) {
41013
41029
  return errorResponse(err);
41014
41030
  }
41015
41031
  });
41032
+ server2.registerTool("list_tags", {
41033
+ title: "List Tags",
41034
+ description: "Discover available tags/labels before searching or tagging content. Returns curated tags (defined by humans), project-specific tags, and tags already in use across items. ALWAYS call this before inventing new tags \u2014 reuse existing ones to keep the knowledge base consistent.",
41035
+ inputSchema: {
41036
+ projectId: external_exports.string().optional().describe("Optional project ID to scope tags to a specific project")
41037
+ }
41038
+ }, async ({ projectId }) => {
41039
+ try {
41040
+ const result = await api.getTags(projectId);
41041
+ return json2(result);
41042
+ } catch (err) {
41043
+ return errorResponse(err);
41044
+ }
41045
+ });
41016
41046
  server2.registerTool("add_knowledge", {
41017
41047
  title: "Add Knowledge",
41018
- description: "Add a knowledge item. Knowledge items are tasks with knowledge:true \u2014 they store decisions, patterns, references, and institutional memory. They reuse the task infrastructure but skip the checkbox/completion workflow.",
41048
+ description: "Add a knowledge item. Knowledge items are tasks with knowledge:true \u2014 they store decisions, patterns, references, and institutional memory. They reuse the task infrastructure but skip the checkbox/completion workflow. Call list_tags first to reuse existing labels.",
41019
41049
  inputSchema: {
41020
41050
  itemId: external_exports.string().describe("The item ID"),
41021
41051
  columnId: external_exports.string().describe("The column ID"),
@@ -41095,7 +41125,7 @@ function registerTools(server2) {
41095
41125
  });
41096
41126
  server2.registerTool("find_knowledge", {
41097
41127
  title: "Find Knowledge",
41098
- description: "Search for knowledge items across all items. Returns tasks with knowledge:true OR tasks that have learnings. Use this to find institutional memory, past decisions, and patterns.",
41128
+ description: "Search specifically for curated knowledge items (knowledge:true) and tasks with captured learnings. Use for institutional decisions, patterns, and reference. For broader task history including descriptions, use search_context instead. Use list_tags to discover valid label values.",
41099
41129
  inputSchema: {
41100
41130
  query: external_exports.string().optional().describe("Text to search for in knowledge items"),
41101
41131
  label: external_exports.string().optional().describe("Filter by label (without #)")
@@ -41118,14 +41148,18 @@ function registerTools(server2) {
41118
41148
  task.content,
41119
41149
  task.description,
41120
41150
  task.acceptanceCriteria,
41121
- task.learnings
41151
+ task.learnings,
41152
+ ...item.meta?.tags ?? []
41122
41153
  ].filter(Boolean).join(" ").toLowerCase();
41123
41154
  if (!searchable.includes(q)) continue;
41124
41155
  }
41125
41156
  if (label) {
41126
41157
  const hasLabel = task.metadata?.labels?.includes(label);
41127
41158
  const hasInlineTag = task.learnings?.toLowerCase().includes(`#${label.toLowerCase()}`);
41128
- if (!hasLabel && !hasInlineTag) continue;
41159
+ const hasFrontmatterTag = item.meta?.tags?.some(
41160
+ (t) => t.toLowerCase() === label.toLowerCase()
41161
+ );
41162
+ if (!hasLabel && !hasInlineTag && !hasFrontmatterTag) continue;
41129
41163
  }
41130
41164
  results.push({
41131
41165
  itemId: itemSummary.id,
@@ -41153,7 +41187,7 @@ function registerTools(server2) {
41153
41187
  description: "Gather all knowledge about a topic and return a structured summary. This collects and organizes existing knowledge items \u2014 it does NOT generate AI content. Returns a paste-ready context brief.",
41154
41188
  inputSchema: {
41155
41189
  topic: external_exports.string().describe('Topic to synthesize knowledge about (e.g. "authentication", "pricing", "deployment")'),
41156
- labels: external_exports.string().optional().describe('Comma-separated labels to filter by (e.g. "backend,security")')
41190
+ labels: external_exports.string().optional().describe('Comma-separated labels to filter by (e.g. "backend,security"). Unlike label on other tools which takes a single value, this accepts multiple comma-separated.')
41157
41191
  }
41158
41192
  }, async ({ topic, labels }) => {
41159
41193
  try {
@@ -41340,12 +41374,13 @@ function registerSystemPrompts(server2) {
41340
41374
 
41341
41375
  ## Core Concepts
41342
41376
 
41343
- AutoMD has three item types:
41377
+ AutoMD has four item types:
41344
41378
  - **Boards** \u2014 Kanban-style markdown files with columns (H1) and tasks (H2). Each has YAML frontmatter with metadata.
41345
41379
  - **Checklists** \u2014 Task lists using ## (H2) headings with [ ]/[x] checkbox prefixes. Great for simple to-do lists and tracking.
41346
- - **Pages** \u2014 Free-form markdown documents for knowledge, specs, documentation, and reference material.
41380
+ - **Pages** \u2014 Free-form markdown documents for specs, documentation, and reference material.
41381
+ - **Knowledge Bases** \u2014 Structured collections of knowledge entries (## H2) without checkboxes or progress tracking. Ideal for decisions, patterns, and institutional memory.
41347
41382
 
41348
- All three types support YAML frontmatter, descriptions, acceptance criteria, subtasks, and learnings.
41383
+ All four types support YAML frontmatter, descriptions, acceptance criteria, subtasks, and learnings.
41349
41384
 
41350
41385
  **Knowledge items** are tasks with \`knowledge:true\` \u2014 they store decisions, patterns, references, and institutional memory. They use the same task infrastructure but represent knowledge, not work to be done.
41351
41386
 
@@ -41389,7 +41424,7 @@ Description paragraph \u2014 background, context, the "why".
41389
41424
  - Use \`synthesize_topic\` to assemble context briefs about a topic
41390
41425
 
41391
41426
  ## Available Tools
41392
- - Item management: list_items, get_item, create_item (supports board/checklist/page types), delete_item, rename_item
41427
+ - Item management: list_items, get_item, create_item (supports board/checklist/page/knowledge types), delete_item, rename_item
41393
41428
  - Task management: add_task, update_task, toggle_task, move_task, delete_task
41394
41429
  - Metadata: update_task_metadata, update_acceptance_criteria, update_learnings
41395
41430
  - Knowledge: add_knowledge, update_knowledge, find_knowledge, synthesize_topic, import_memories
@@ -41433,7 +41468,7 @@ Please:
41433
41468
  3. Identify any dependencies between subtasks
41434
41469
  4. Suggest which subtasks could be parallelized
41435
41470
 
41436
- Provide the specific add_subtask tool calls to create each subtask.`
41471
+ Subtasks are GFM checkboxes (\`- [ ] text\`) inside the parent task's content. Use update_task to add them to the parent task's body, or use add_task to create standalone tasks.`
41437
41472
  }
41438
41473
  }]
41439
41474
  };
@@ -41741,7 +41776,7 @@ Analyze completed tasks and the board state to provide:
41741
41776
  3. **Action Items** \u2014 Concrete improvements for next iteration
41742
41777
  4. **Learnings to Capture** \u2014 Key decisions and patterns worth preserving as knowledge items
41743
41778
 
41744
- For each learning worth capturing, provide add_knowledge or add_learning tool calls so they're preserved for future reference.`
41779
+ For each learning worth capturing, provide add_knowledge tool calls for new knowledge items, or update_learnings tool calls to attach learnings to existing tasks.`
41745
41780
  }
41746
41781
  }]
41747
41782
  };
package/package.json CHANGED
@@ -1,40 +1,41 @@
1
- {
2
- "name": "automd-mcp",
3
- "version": "0.2.0",
4
- "description": "MCP server for AutoMD — manage boards, checklists, and pages stored as markdown",
5
- "type": "module",
6
- "main": "./dist/index.js",
7
- "bin": {
8
- "automd-mcp": "./dist/index.js"
9
- },
10
- "files": [
11
- "dist"
12
- ],
13
- "keywords": [
14
- "mcp",
15
- "model-context-protocol",
16
- "kanban",
17
- "markdown",
18
- "automd",
19
- "task-management"
20
- ],
21
- "repository": {
22
- "type": "git",
23
- "url": "https://github.com/luka-zivkovic/automd"
24
- },
25
- "license": "SEE LICENSE IN LICENSE",
26
- "author": "Luka Zivkovic",
27
- "devDependencies": {
28
- "@modelcontextprotocol/sdk": "^1.26.0",
29
- "@types/mdast": "^4.0.4",
30
- "tsup": "^8.0.0",
31
- "tsx": "^4.19.0",
32
- "typescript": "^5.7.2",
33
- "zod": "^4.3.6"
34
- },
35
- "scripts": {
36
- "dev": "tsx watch src/index.ts",
37
- "start": "node dist/index.js",
38
- "build": "tsup"
39
- }
40
- }
1
+ {
2
+ "name": "automd-mcp",
3
+ "version": "0.2.2",
4
+ "description": "MCP server for AutoMD — manage boards, checklists, and pages stored as markdown",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "bin": {
8
+ "automd-mcp": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "dev": "tsx watch src/index.ts",
15
+ "start": "node dist/index.js",
16
+ "build": "tsup",
17
+ "prepublishOnly": "pnpm build"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "model-context-protocol",
22
+ "kanban",
23
+ "markdown",
24
+ "automd",
25
+ "task-management"
26
+ ],
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/luka-zivkovic/automd"
30
+ },
31
+ "license": "SEE LICENSE IN LICENSE",
32
+ "author": "Luka Zivkovic",
33
+ "devDependencies": {
34
+ "@modelcontextprotocol/sdk": "^1.26.0",
35
+ "@types/mdast": "^4.0.4",
36
+ "tsup": "^8.0.0",
37
+ "tsx": "^4.19.0",
38
+ "typescript": "^5.7.2",
39
+ "zod": "^4.3.6"
40
+ }
41
+ }
package/LICENSE.md DELETED
@@ -1,60 +0,0 @@
1
- # License
2
-
3
- Portions of this software are licensed as follows:
4
-
5
- - Content of branches other than the main branch (i.e. "master") is not licensed.
6
- - Source code files that contain ".ee." in their filename or ".ee" in their dirname are NOT licensed under the Sustainable Use License. To use source code files that contain ".ee." in their filename or ".ee" in their dirname you must hold a valid AutoMD Enterprise License specifically allowing you access to such source code files, as defined in "LICENSE_EE.md".
7
- - All third party components incorporated into the AutoMD Software are licensed under the original license provided by the owner of the applicable component.
8
- - Content outside of the above mentioned files or restrictions is available under the "Sustainable Use License" as defined below.
9
-
10
- # Sustainable Use License
11
-
12
- Version 1.0
13
-
14
- ## Acceptance
15
-
16
- By using the software, you agree to all of the terms and conditions below.
17
-
18
- ## Copyright License
19
-
20
- The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations below.
21
-
22
- ## Limitations
23
-
24
- You may use or modify the software only for your own internal business purposes or for non-commercial or personal use. You may distribute the software or provide it to others only if you do so free of charge for non-commercial purposes. You may not provide the software to third parties as a hosted or managed service, where the service provides users with access to any substantial set of the features or functionality of the software. You may not move, change, disable, or circumvent the license key functionality in the software, and you may not remove or obscure any functionality in the software that is protected by the license key. You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensor's trademarks is subject to applicable law.
25
-
26
- ## Patents
27
-
28
- The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
29
-
30
- ## Notices
31
-
32
- You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms. If you modify the software, you must include in any modified copies of the software a prominent notice stating that you have modified the software.
33
-
34
- ## No Other Rights
35
-
36
- These terms do not imply any licenses other than those expressly granted in these terms.
37
-
38
- ## Termination
39
-
40
- If you use the software in violation of these terms, such use is not licensed, and your license will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your license will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your license to terminate automatically and permanently.
41
-
42
- ## No Liability
43
-
44
- As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.
45
-
46
- ## Definitions
47
-
48
- The **licensor** is the entity offering these terms, AutoMD (automd.io).
49
-
50
- The **software** is the software the licensor makes available under these terms, including any portion of it.
51
-
52
- **You** refers to the individual or entity agreeing to these terms.
53
-
54
- **Your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. Control means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
55
-
56
- **Your license** is the license granted to you for the software under these terms.
57
-
58
- **Use** means anything you do with the software requiring your license.
59
-
60
- **Trademark** means trademarks, service marks, and similar rights.