mcpField
E
email-construction

email-construction

github.com/datadrivenconstruction生産性375104 回インストール1 週間前に更新
リポジトリ

email-construction について

建設プロジェクトチーム向けのメール作成スキルです。RFI への回答、サブミッタル、会議、変更指示、遅延通知などの定型メールを作成できます。

主な機能

  1. 01RFI 回答メールの作成
  2. 02サブミッタルと会議メールの作成
  3. 03変更指示と遅延通知の下書き
  4. 04SMTP によるメール送信

活用シーン

  1. 01プロジェクト情報を含む RFI 回答
  2. 02審査用サブミッタルの送付
  3. 03会議や変更事項のチームへの通知

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction --skill email-construction

インストール後、Claude Code で/email-constructionを入力して読み込まれたか確認します。

同梱ファイルclaw.jsoninstructions.md

詳細

建設業向けメールの作成

概要

適切な書式、文脈、添付ファイルの取り扱いに対応した、プロフェッショナルな建設業向けメールを作成します。一般的な建設業のコミュニケーションワークフロー向けのテンプレートを用意しています。

建設業でのユースケース

1. RFI 回答メール

プロフェッショナルな RFI 回答メールを作成します。

from dataclasses import dataclass
from datetime import datetime
from typing import Optional, List

@dataclass
class RFIResponse:
    rfi_number: str
    project_name: str
    subject: str
    question: str
    response: str
    responder_name: str
    responder_title: str
    attachments: List[str] = None
    cc_list: List[str] = None

def generate_rfi_response_email(rfi: RFIResponse) -> dict:
    """Generate RFI response email."""

    subject = f"RE: RFI #{rfi.rfi_number} - {rfi.subject}"

    body = f"""Dear Project Team,

Please find below our response to RFI #{rfi.rfi_number}.

**Project:** {rfi.project_name}
**RFI Number:** {rfi.rfi_number}
**Subject:** {rfi.subject}
**Date:** {datetime.now().strftime('%B %d, %Y')}

---

**QUESTION:**
{rfi.question}

---

**RESPONSE:**
{rfi.response}

---

Please proceed accordingly. If you have any questions regarding this response, please contact us.

{"**Attachments:**" + chr(10) + chr(10).join(f"- {a}" for a in rfi.attachments) if rfi.attachments else ""}

Best regards,

{rfi.responder_name}
{rfi.responder_title}
"""

    return {
        'subject': subject,
        'body': body,
        'cc': rfi.cc_list or [],
        'attachments': rfi.attachments or []
    }
2. サブミッタルトランスミッタルメール

サブミッタルトランスミッタルメールを作成します。

@dataclass
class SubmittalTransmittal:
    submittal_number: str
    project_name: str
    spec_section: str
    description: str
    items: List[dict]
    action_required: str
    due_date: str
    sender_name: str
    sender_company: str

def generate_submittal_email(submittal: SubmittalTransmittal) -> dict:
    """Generate submittal transmittal email."""

    subject = f"Submittal {submittal.submittal_number} - {submittal.spec_section} - {submittal.description}"

    items_list = "\n".join(
        f"   {i+1}. {item['description']} ({item.get('copies', 1)} copies)"
        for i, item in enumerate(submittal.items)
    )

    body = f"""Dear Design Team,

Please find attached Submittal {submittal.submittal_number} for your review.

**Project:** {submittal.project_name}
**Submittal No:** {submittal.submittal_number}
**Spec Section:** {submittal.spec_section}
**Description:** {submittal.description}

**Items Transmitted:**
{items_list}

**Action Required:** {submittal.action_required}
**Response Requested By:** {submittal.due_date}

Please review and return with your comments at your earliest convenience.
If you have any questions, please don't hesitate to contact us.

Best regards,

{submittal.sender_name}
{submittal.sender_company}
"""

    return {
        'subject': subject,
        'body': body,
        'priority': 'normal'
    }
3. 会議通知メール

会議の招待メールを作成します。

@dataclass
class MeetingNotice:
    meeting_type: str  # 'OAC', 'Subcontractor', 'Safety', 'Coordination'
    project_name: str
    date: str
    time: str
    location: str
    virtual_link: Optional[str]
    agenda_items: List[str]
    attendees: List[str]
    organizer_name: str

def generate_meeting_notice(meeting: MeetingNotice) -> dict:
    """Generate meeting notice email."""

    subject = f"{meeting.meeting_type} Meeting - {meeting.project_name} - {meeting.date}"

    agenda = "\n".join(f"   {i+1}. {item}" for i, item in enumerate(meeting.agenda_items))

    location_info = meeting.location
    if meeting.virtual_link:
        location_info += f"\n   Virtual Option: {meeting.virtual_link}"

    body = f"""Dear Team,

You are invited to the {meeting.meeting_type} Meeting for {meeting.project_name}.

**Meeting Details:**
- **Date:** {meeting.date}
- **Time:** {meeting.time}
- **Location:** {location_info}

**Agenda:**
{agenda}

**Attendees:**
{', '.join(meeting.attendees)}

Please confirm your attendance by replying to this email.
If you cannot attend, please send a delegate and notify the organizer.

Regards,

{meeting.organizer_name}
Project Manager
"""

    return {
        'subject': subject,
        'body': body,
        'to': meeting.attendees,
        'calendar_invite': {
            'start': f"{meeting.date} {meeting.time}",
            'duration': 60,
            'location': meeting.location
        }
    }
4. 変更指示通知

変更指示の通知メールを作成します。

@dataclass
class ChangeOrderNotification:
    co_number: str
    project_name: str
    description: str
    amount: float
    schedule_impact: str
    reason: str
    status: str  # 'Pending', 'Approved', 'Rejected'
    sender_name: str
    sender_title: str

def generate_change_order_email(co: ChangeOrderNotification) -> dict:
    """Generate change order notification email."""

    subject = f"Change Order #{co.co_number} - {co.status} - {co.project_name}"

    amount_str = f"${co.amount:,.2f}"
    if co.amount < 0:
        amount_str = f"(${abs(co.amount):,.2f}) Credit"

    body = f"""Dear Project Team,

This email is to notify you of Change Order #{co.co_number} for {co.project_name}.

**Change Order Details:**
- **CO Number:** {co.co_number}
- **Status:** {co.status}
- **Description:** {co.description}

**Financial Impact:**
- **Amount:** {amount_str}

**Schedule Impact:**
- {co.schedule_impact}

**Reason for Change:**
{co.reason}

{"Please review the attached documentation and provide your approval." if co.status == 'Pending' else ""}
{"This change order has been approved. Please proceed accordingly." if co.status == 'Approved' else ""}

If you have any questions, please contact the project team.

Best regards,

{co.sender_name}
{co.sender_title}
"""

    return {
        'subject': subject,
        'body': body,
        'priority': 'high' if co.status == 'Pending' else 'normal',
        'flag': co.status == 'Pending'
    }
5. 日報メール

日報の配信メールを作成します。

@dataclass
class DailyReportEmail:
    project_name: str
    report_date: str
    report_number: int
    weather: str
    workforce_total: int
    work_summary: List[str]
    issues: List[str]
    sender_name: str

def generate_daily_report_email(report: DailyReportEmail) -> dict:
    """Generate daily report distribution email."""

    subject = f"Daily Report #{report.report_number} - {report.project_name} - {report.report_date}"

    work_items = "\n".join(f"• {item}" for item in report.work_summary)
    issues_text = "\n".join(f"• {issue}" for issue in report.issues) if report.issues else "None"

    body = f"""Daily Construction Report

**Project:** {report.project_name}
**Date:** {report.report_date}
**Report #:** {report.report_number}

---

**Weather:** {report.weather}
**Total Workforce:** {report.workforce_total} workers on-site

---

**Work Completed:**
{work_items}

---

**Issues/Delays:**
{issues_text}

---

Full report attached. Please contact the site office with any questions.

{report.sender_name}
Site Superintendent
"""

    return {
        'subject': subject,
        'body': body,
        'attachments': [f'Daily_Report_{report.report_number}.pdf']
    }
6. 遅延通知メール

正式な遅延通知を作成します。

@dataclass
class DelayNotice:
    project_name: str
    contract_number: str
    delay_type: str  # 'Excusable', 'Non-Excusable', 'Compensable'
    cause: str
    affected_activities: List[str]
    original_completion: str
    revised_completion: str
    days_impacted: int
    mitigation_plan: str
    sender_name: str
    sender_title: str

def generate_delay_notice_email(delay: DelayNotice) -> dict:
    """Generate formal delay notice email."""

    subject = f"NOTICE OF DELAY - {delay.project_name} - {delay.days_impacted} Days"

    activities = "\n".join(f"   - {a}" for a in delay.affected_activities)

    body = f"""NOTICE OF DELAY

**Project:** {delay.project_name}
**Contract No:** {delay.contract_number}
**Date:** {datetime.now().strftime('%B %d, %Y')}

---

Dear Owner/Owner's Representative,

In accordance with the contract requirements, this letter serves as formal notice of a delay to the project schedule.

**Delay Classification:** {delay.delay_type}

**Cause of Delay:**
{delay.cause}

**Affected Activities:**
{activities}

**Schedule Impact:**
- Original Completion Date: {delay.original_completion}
- Revised Completion Date: {delay.revised_completion}
- Calendar Days Impacted: {delay.days_impacted}

**Mitigation Plan:**
{delay.mitigation_plan}

We request a meeting to discuss this matter and coordinate recovery efforts. Please contact us at your earliest convenience.

This notice is provided without prejudice to any rights or remedies available under the contract.

Respectfully,

{delay.sender_name}
{delay.sender_title}
"""

    return {
        'subject': subject,
        'body': body,
        'priority': 'high',
        'read_receipt': True,
        'delivery_receipt': True
    }

メール送信の連携

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication

class ConstructionEmailSender:
    """Send construction emails via SMTP."""

    def __init__(self, smtp_server: str, smtp_port: int, username: str, password: str):
        self.smtp_server = smtp_server
        self.smtp_port = smtp_port
        self.username = username
        self.password = password

    def send(self, to: List[str], email_data: dict, from_addr: str = None):
        """Send email with optional attachments."""
        msg = MIMEMultipart()
        msg['From'] = from_addr or self.username
        msg['To'] = ', '.join(to)
        msg['Subject'] = email_data['subject']

        if email_data.get('cc'):
            msg['Cc'] = ', '.join(email_data['cc'])

        if email_data.get('priority') == 'high':
            msg['X-Priority'] = '1'

        msg.attach(MIMEText(email_data['body'], 'plain'))

        # Add attachments
        for attachment_path in email_data.get('attachments', []):
            with open(attachment_path, 'rb') as f:
                part = MIMEApplication(f.read())
                part.add_header('Content-Disposition', 'attachment',
                               filename=attachment_path.split('/')[-1])
                msg.attach(part)

        # Send
        with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
            server.starttls()
            server.login(self.username, self.password)

            recipients = to + email_data.get('cc', [])
            server.sendmail(msg['From'], recipients, msg.as_string())

DDC パイプラインとの連携

# Example: Auto-generate RFI response email from RFI log
import pandas as pd

# Load RFI log
rfi_log = pd.read_excel("RFI_Log.xlsx")

# Get pending RFI
pending_rfi = rfi_log[rfi_log['status'] == 'Response Ready'].iloc[0]

# Generate email
rfi = RFIResponse(
    rfi_number=pending_rfi['rfi_number'],
    project_name=pending_rfi['project'],
    subject=pending_rfi['subject'],
    question=pending_rfi['question'],
    response=pending_rfi['response'],
    responder_name='John Smith',
    responder_title='Project Architect',
    attachments=['SK-001.pdf']
)

email_data = generate_rfi_response_email(rfi)
print(f"Subject: {email_data['subject']}")
print(email_data['body'])

メールテンプレートライブラリ

建設業でよく使用されるメールテンプレート:

テンプレートユースケース
RFI 回答情報提供依頼への回答
サブミッタルトランスミッタルレビュー用のサブミッタルの送付
会議通知OAC、協力会社、安全に関する会議
変更指示CO の通知と承認
日報日報の配信
遅延通知正式な遅延通知
支払申請支払申請の提出
パンチリストパンチリスト項目の通知
クローズアウト保証書およびクローズアウト書類

リソース

  • プロフェッショナルなメールの書き方:メールは簡潔で、具体的なアクションにつながる内容にします
  • 建設業のメール作成におけるベストプラクティス:プロジェクト名と参照番号を必ず記載します
  • 法的な考慮事項:遅延通知には契約上の要件が定められている場合があります

コメント